与这个'混淆javascript

时间:2017-10-02 02:29:12

标签: javascript this

我对javascript'这个'有疑问。我明白这个'这个'是指调用函数的对象。在示例1中,如果我们调用obj.bar(),为什么this.x = 4

var x = 4,
obj = {
    x: 3,
    bar: function() {
        var x = 2;
        setTimeout(function() {
            var x = 1;
            alert(this.x);
        }, 1000);
    }
};
obj.bar();

输出:4

在下面的代码中,为什么this.x = 3和1之后:

var x = 3;
var foo = {
    x: 2,
    baz: {
        x: 1,
        bar: function() {
            return this.x;
        }
    }
}
var go = foo.baz.bar;
alert(go());
alert(foo.baz.bar());

输出: 3,1

2 个答案:

答案 0 :(得分:3)

创建函数时未确定

this。确定何时调用函数。

在setTimeout的情况下,一旦经过一定的时间,该功能就会被突然执行。没有上下文,因此浏览器在全局上下文中调用该函数。你碰巧声明了一个x=4的全局变量,所以这就是this.x将会相同的。如果您使用严格模式(通过在脚本顶部添加"use strict";),那么对于setTimeout情况,this将是未定义的,您将收到错误。

当你调用go()时,你有一个没有上下文的独立函数,所以它在全局上下文中再次被调用。这导致它使用你的全局x = 3。

当你致电foo.baz.bar()时,你终于有了一个上下文。上下文为foo.baz,因此this引用的内容为this.x,等同于foo.baz.x,等于1。

答案 1 :(得分:3)

当您在最顶层声明变量时,您将在aging(&ps[1])对象中创建一个全局变量。顶级关键字window是指this

window

当您致电var x = 4; // same as `window.x = 4`; console.log(x); // same as `console.log(this.x)`; 时,obj.bar()关键字会引用this内的obj。但是在bar里面你有一个不同的setTimeout,它是指你传递给this的回调的调用者。此调用者未指定setTimeout的值,因此它只是成为this对象。因此,在此代码中:

window

setTimeout(function() { var x = 1; alert(this.x); }, 1000); this.x相同,正如您在全局范围内定义的那样window.x

解决第二个例子,当你为一个变量分配一个函数时,你会失去该函数的来源上下文:

4

现在,当您通知var go = foo.baz.bar; 时,该调用中没有任何点,这意味着没有明确的对象访问权,这意味着没有隐式go()。在这种情况下,您仍然可以使用this

传递this
call

您可以使用use strict避免许多这些问题。在严格模式下,// outputs `3` because `this` is `window`, and `window.x` is `3` // as declared in the global scope alert(go()); // Will output `2` because `this` is `foo` alert(go.call(foo)); // Will output `1` because `this` is `foo.baz` alert(go.call(foo.baz)); // Will output `1` because the implicit value of `this` is `foo.baz` // since we have an explicit object access in this function call alert(foo.baz.bar()); 在未明确或隐式定义时将是未定义的,而不是默认为this对象。