Nad*_*oli 5 javascript scope this
我正在阅读一些关于javascript的文档,并偶然发现了以下代码示例:
var o = {
value: 1,
outer: function () {
var inner = function () {
console.log(this); //bound to global object
};
inner();
}
};
o.outer();
Run Code Online (Sandbox Code Playgroud)
它输出window.
我想不通,为什么是this(绑定到全局对象的关键字window),而不是父对象(outer).
如果outer要从inner范围访问,则必须将outers this(就像传递outer自身一样)inner作为参数传递给其本地函数.所以,正如所料:
var o = {
value: 1,
outer: function () {
var inner = function (that) {
console.log(that); //bound to global object
};
inner(this);
}
};
o.outer();
Run Code Online (Sandbox Code Playgroud)
输出outer.
是不是有点在一个废话outer的范围this被绑定到对象本身(即outer),而在inner的范围,这是局部的outer,this被重新绑定到全局对象(即它覆盖outer的捆绑)?
所述的ECMAScript规格规定,输入功能代码的执行上下文时,如果«提供thisArg呼叫者»要么是空或未定义,然后this被绑定到全局对象.
但是以下内容:
var o = {
outer: function () {
var inner = function () {
console.log('caller is ' + arguments.callee.caller);
};
inner();
}
}
Run Code Online (Sandbox Code Playgroud)
输出对象outer本身:
caller is function () {
var inner = function () {
console.log('caller is ' + arguments.callee.caller);
};
inner();
}
Run Code Online (Sandbox Code Playgroud)
另一方面,但可能是相关的,请注意:
在严格模式下,第一个代码段输出undefined而不是窗口.
这是因为this在运行函数时设置,而不是在定义函数时设置.
例如:
var o = {
func: function(){
console.log(this);
}
};
Run Code Online (Sandbox Code Playgroud)
当你打电话时o.func(),你是在上下文中这样做的o,所以它按预期工作.
现在让我们说你这样做:
var f = o.func;
f();
Run Code Online (Sandbox Code Playgroud)
这不会按预期工作.这是因为,当你调用f(),它没有任何上下文连接到它,所以this会window.
您可以通过使用.call更改值来解决此问题this.
var f = o.func;
f.call(o); // sets `this` to `o` when calling it
Run Code Online (Sandbox Code Playgroud)
这就是语言的工作原理。
每次调用函数时,this都会被重置。在嵌套(内部)函数中,它不会像其他(显式声明的)变量那样从封闭范围继承值。
默认情况下 this将设置为window,除非该函数被调用为:
myObj.func(arg1, ...)或者func.call(myObj, arg1, ...)或者func.apply(myObj, [arg1, ...])在这种情况下this将等于myObj
以任何其他方式调用的函数,即使它最初被定义为对象的属性(var func = myObj.func; func()即将使用window.
还有一个名为 的实用函数.bind,它以这样的方式包装函数引用,您可以提供一个始终用作的特定值this:
var myFunc = myObj.func; // obtain reference to func
var bound = myFunc.bind(someOtherObj); // bind it to "someOtherObj"
bound(); // this === someOtherObj
bound.call(myObj) // this still === someOtherObj
Run Code Online (Sandbox Code Playgroud)