深入理解JavaScript系列(13) This? Yes,this!(4)


try {
throw function () {
alert(this);
};
} catch (e) {
e(); // ES3标准里是__catchObject, ES5标准里是global
}

// on idea

var eReference = {
base: __catchObject,
propertyName: 'e'
};

// ES5新标准里已经fix了这个bug,
// 所以this就是全局对象了
var eReference = {
base: global,
propertyName: 'e'
};


同样的情况出现在命名函数(函数的更对细节参考第15章Functions)的递归调用中。在函数的第一次调用中,base对象是父活动对象(或全局对象),在递归调用中,base对象应该是存储着函数表达式可选名称的特定对象。但是,在这种情况下,this总是指向全局对象。

复制代码 代码如下:


(function foo(bar) {

alert(this);

!bar && foo(1); // "should" be special object, but always (correct) global

})(); // global


作为构造器调用的函数中的this
还有一个与this值相关的情况是在函数的上下文中,这是一个构造函数的调用。

复制代码 代码如下:


function A() {
alert(this); // "a"对象下创建一个新属性
this.x = 10;
}

var a = new A();
alert(a.x); // 10


在这个例子中,new运算符调用“A”函数的内部的[[Construct]] 方法,接着,在对象创建后,调用内部的[[Call]] 方法。 所有相同的函数“A”都将this的值设置为新创建的对象。

函数调用中手动设置this
在函数原型中定义的两个方法(因此所有的函数都可以访问它)允许去手动设置函数调用的this值。它们是.apply和.call方法。他们用接受的第一个参数作为this值,this 在调用的作用域中使用。这两个方法的区别很小,对于.apply,第二个参数必须是数组(或者是类似数组的对象,如arguments,反过来,.call能接受任何参数。两个方法必须的参数是第一个——this。

例如:

复制代码 代码如下:


var b = 10;

function a(c) {
alert(this.b);
alert(c);
}

a(20); // this === global, this.b == 10, c == 20

a.call({b: 20}, 30); // this === {b: 20}, this.b == 20, c == 30
a.apply({b: 30}, [40]) // this === {b: 30}, this.b == 30, c == 40


结论
在这篇文章中,我们讨论了ECMAScript中this关键字的特征(对比于C++ 和 Java,它们的确是特色)。我希望这篇文章有助于你准确的理解ECMAScript中this关键字如何工作。同样,我很乐意在评论中回到你的问题。

其它参考
10.1.7 – 11.1.1 – 11.2.2 – 11.2.3 –

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdjdzg.html