this in JavaScript in detail

  sonic0002        2013-05-09 18:35:12       3,959        0          English  简体中文  繁体中文  ภาษาไทย  Tiếng Việt 

在 JavaScript 中,this 總是令人困惑,它是 JavaScript 中最常見的陷阱之一。在 JavaScript 中,這不是一個好的設計(您可以參考 JavaScript 的其他一些設計缺陷這裡),由於它的惰性綁定特性,它可以是一個全域物件、當前物件,或是...。有些人甚至避免在 JavaScript 中使用 this

實際上,如果您掌握了 this 的工作原理,那麼您就會知道如何避開這些陷阱。讓我們看看在以下情況下 this 指向什麼。

1. 在全域範圍程式碼中

alert(this)//window

在全域範圍程式碼中,this 將指向全域物件(通常在 Web 瀏覽器中是 window)。

2. 在純函數呼叫中

function fooCoder(x) {
	this.x = x;
}
fooCoder(2);
alert(x);// Global variable x's value is 2

這裡 this 也指向全域物件,因為在全域範圍中定義的函數實際上是全域物件的一個方法。所以 this 將是全域物件。在嚴格模式下,this 將是 undefined

3. 在物件的方法呼叫中

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		console.log(this.name + " says " + sth);
	}
}
person.hello("hello world");

輸出將是 "foocoder says hello world"。this 將指向 person 物件,也就是呼叫該方法的當前物件。

4. 在建構子中

new FooCoder();

在建構子中,this 將指向使用 new 新建立的物件。

5. 在私有函數呼叫中

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		var sayhello = function(sth) {
			console.log(this.name + " says " + sth);
		};
		sayhello(sth);
	}
}
person.hello("hello world");//clever coder says hello world

在私有函數中,this 不會綁定到外部方法的物件,而是綁定到全域物件。這被認為是 JavaScript 的設計缺陷,因為沒有人希望私有函數中的 this 在這裡指向全域物件。一般的解決方案是將 this 賦值給另一個變數,並在私有函數中引用該變數。

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		var that = this;
		var sayhello = function(sth) {
			console.log(that.name + " says " + sth);
		};
		sayhello(sth);
	}
}
person.hello("hello world");//foocoder says hello world

6. 在 call() 或 apply() 中

person.hello.call(person, "world");

apply()call() 類似,唯一的區別是第一個參數之後傳入的參數。在 apply() 中,其他參數將以陣列形式傳入,而在 call() 中,其他參數將分別傳入。

call( thisArg [,arg1,arg2,… ] );  // Parameter list,arg1,arg2,...
apply(thisArg [,argArray] );     // Parameter list,argArray

傳入的第一個參數是 this 將指向的物件。我們可以指定任何要讓 this 指向的物件。

7. 其他

我們可能會經常看到以下程式碼:

$("#some-ele").click = obj.handler;

如果我們在 handler 中使用 thisthis 會綁定到 obj 嗎?顯然不會,在賦值之後,函數是在回呼函數中呼叫的,this 將綁定到 $("#some-div") 元素。這是我們需要理解的——執行上下文。

那麼我們如何在回呼函數中指定 this 物件為我們想要的物件呢?在 ECMAScript 5 中,有一個 bind() 方法:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg 將是我們想要成為的 this 物件。

$("#some-ele").click(person.hello.bind(person));

現在 this 將是 person 物件

在 Prototype.js 中,我們可以找到 bind() 的實現:

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

結論

1. 當函數作為物件的方法呼叫時,this 將指向該物件

2. 當在純函數呼叫中時,this 將是全域物件(在嚴格模式下,this 將是 undefined

3. 在建構子中,this 將是新建立的物件

一句話概括,this 總是會指向呼叫該函數的物件。

GUIDE  BIND  THIS  JAVASCRIPT 

           

  RELATED


  0 COMMENT


No comment for this article.



  PROGRAMMER HUMOR

First law of software quality


  SUPPORT US