参考自:深入理解javascript原型和闭包(10)——this(王福朋 - 博客园)。如有侵权,请联系删除。
在具体了解 this 之前,先强调一个非常重要的知识点:在函数中 this 到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。因为 this 的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。
this的取值,分四种情况。我们来挨个看一下。
情况1:构造函数
所谓构造函数就是用来 new 对象的函数。其实严格来说,所有的函数都可以 new 一个对象,但是有些函数的定义是为了 new 一个对象,而有些函数则不是。另外注意,构造函数的函数名第一个字母大写(规则约定)。例如:Object、Array、Function 等。
function Foo() { |
以上代码中,如果函数作为构造函数用,那么其中的 this 就代表它即将 new 出来的对象。
以下有两个需要注意的地方:
1、情况1 仅限 Foo 函数作为构造函数的情况。如果直接调用 Foo 函数,而不是 new Foo(),情况就大不一样了(this 指向 Window)。
function Foo() { |
2、在构造函数的 prototype 中,this 指向的是构造的对象:
function Foo() { |
其实,不仅仅是构造函数的 prototype,即便是在整个原型链中,this 代表的也都是当前对象的值。
情况2:函数作为对象的一个属性
如果函数作为对象的一个属性时,并且作为对象的一个属性被调用时,函数中的 this 指向该对象。
var obj = { |
以上代码中,fn 不仅作为一个对象的一个属性,而且的确是作为对象的一个属性被调用。结果 this 就是 obj 对象。
注意,如果fn函数不作为obj的一个属性被调用,会是什么结果呢?
var obj = { |
如上代码,如果 fn 函数被赋值到了另一个变量中,并没有作为 obj 的一个属性被调用,那么 this 的值就是 Window,this.x 为 undefined。
情况3:函数用 call 或者 apply 调用
当一个函数被 call 和 apply 调用时,this 的值就取传入的对象的值。
var obj = { |
情况4:全局 & 调用普通函数
这一部分代码都很好理解:
console.log(this === window); // true |
需要注意的是,如果在对象内的函数属性中调用一个函数,这个被调用的函数属于调用普通函数,而不属于情况2 :
var obj = { |
一个经典的 jQuery 源码案例
jQuery.extend = jQuery.fn.extend = function() { |
以上代码是从 jQuery 中摘除来的部分代码。jQuery.extend 和 jQuery.fn.extend 都指向了同一个函数,但是当执行时,函数中的 this 是不一样的。
执行 jQuery.extend(…) 时,this 指向 jQuery;执行 jQuery.fn.extend(…) 时,this 指向 jQuery.fn。
这样就巧妙的将一段代码同时共享给两个功能使用,更加符合设计原则。