1. 程式人生 > >js的this指標指向誰,以及相關的call、apply、bind方法

js的this指標指向誰,以及相關的call、apply、bind方法

1、誰作為呼叫者就指向誰

function a() {  
	    console.log(this);  
	}  

	//下面a方法的呼叫,其實在js中等於window.a(),也就是window呼叫了a()方法,所以a方法中的this指向了window
	a(); //this指向window物件

	/*下面這方法其實將a方法賦值給了b物件的say方法,呼叫say方法(也就是a方法)的是b物件,所以此時this指向b物件。
	  你可能會說b.say()不就等於window.b.say()方法嗎?為什麼不是this不是指向window呢?
	  其實在下面這個環境b物件是當前window下的一個屬性。呼叫say方法的是b物件。所以this是指向b的
	*/
	var b  = {};  
	b.say = a; 
	b.say(); //此時的this指向了b物件

2、沒有擁有者,直接呼叫,就指向window

function a() {  
	    console.log(this);  
	}  

3、另外一個例子

我們在js中可以使用document.write()方法向網頁中輸入文字內容。如
document.write("aaaa"); 網頁中就會被加入aaaa文字。
但是如果我們像下面這麼寫呢?

var myWrite = document.write;
myWrite("aaaa");
上面的程式碼首先是我將document.write方法賦值給myWrite方法。然後使用myWrite()方法向網頁中輸入文字內容。但是這裡會報錯,為什麼呢?

原因就在這個write方法的this指標的域被改變啦!
document.write()方法的this是指向document的。所以可以

網頁中輸入文字內容
但是我們將document.write方法賦值給myWrite物件,然後在呼叫myWrite()方法。呼叫myWrite()方法的物件域是全域性變數window,
相當於window.myWrite()。此時this指向window,而不指向document.所以會報錯。

4、遇到上面的this域被改變了,我們怎麼辦呢?

改變this域的三個方法bind()、call()、apply()。這三個方法js所有的Function物件都具有

4.1 使用bind方法
a.bind(b);  就是將a()方法的this指標的作用域繫結到b物件的作用域上,也就是現在a的this指標的作用域就是b
如是上面的程式碼就可以改成:

document.write("aaaa"); 
	var myWrite = document.write;
	myWrite.bind(document)("aaaa"); //網頁中輸入aaaa。此時的this指標指向了bind()的document。
4.2 使用call方法
call(a, b); a是當前方法需要執行域,後面的b是當前方法的引數,可以傳多個引數,多個引數直接用逗號隔開即可,如 call(a, b, c, d); b, c, d都是方法的引數
上面的程式碼用call來改寫就是:
document.write("aaaa"); 
	var myWrite = document.write;
	myWrite.call(document, "aaaa");
4.3 使用apply方法

apply(a, b) a是當前方法需要執行的域,後面的b是當前方法的引數,可以傳多個引數,多個引數需要使用陣列來傳入。如apply(a, [b, c, d]);b、c、d為引數
上面程式碼用apply來改寫就是:

document.write("aaaa"); 
	var myWrite = document.write;
	myWrite.call(document, "aaaa"); 
5、思考:

程式碼片段一

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()()); //指向其中的this指向window,因為沒有擁有者,所以結果就是"The Window"

程式碼片段二
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
    //在getNameFunc方法中將this繫結到that物件上,而that屬於getNameFunc函式的內部變數,而這個函式的執行域是object。所以結果是"My Object"
  alert(object.getNameFunc()());