【问题标题】:why the code this point to window object?为什么这个代码指向窗口对象?
【发布时间】:2012-09-03 03:37:07
【问题描述】:

我的代码是:

var length = 20;
function fn(){
    console.log(this.length);
}

var o = {
    length:10,
    e:function (fn){
       fn();
       arguments[0]();
    }
}

o.e(fn);

输出是20,1,谁能告诉我为什么?

【问题讨论】:

  • 阅读callapply
  • @muistooshort 你说的是fn()arguments[0](),一个叫call,另一个叫apply
  • 在第一个呼叫中您获得 20 this === window,在第二个呼叫中获得 this===arguments。将 console.log 更改为 console.log(this.length,this); 并将调用更改为 o.e(fn,'test'); ,您会看到您获得了参数数组。
  • @dbaseman:这些更多是关于用明确的this 来做fn()arguments[0]() 的行为与它一样,因为有一个隐藏点,所以它有点像在说 arguments.0()(如果后者当然是有效的 JavaScript)。

标签: javascript arguments this


【解决方案1】:

this 关键字出现在函数内部时,其值取决于函数的调用方式

在您的情况下,调用 fn() 时未提供 this 值,因此默认值为 window。 对于arguments[0](),上下文是arguments 对象,其长度为1

关键是函数在哪里被调用并不重要,重要的是函数如何被调用

var length = 20;
function fn(){
    console.log(this.length);
}

var o = {
    length:10,
    e:function (fn){
       fn(); // this will be the window.
       arguments[0](); // this will be arguments object.
    }
}

o.e(fn);

此外,如果您希望this 成为对象o,您可以先使用callapply,或bind 一个对象。

var length = 20;
function fn(){
    console.log(this.length);
}

var o = {
    length:10,
    e:function (fn){
       var fn2 = fn.bind(this);
       fn.call(this); // this in fn will be the object o.
       fn.apply(this); // this in fn will be the object o.
       fn2(); // this also will be the object o.
    }
}

o.e(fn);

【讨论】:

  • this 不是上下文,它是执行上下文(或 ES5 中的词法环境)的一个组件。你应该写fn() is called without providing a this value。调用 this 上下文只是令人困惑。
  • 哦,如果代码处于严格模式,则会引发类型错误,因为如果未提供值,它将不会将 this 设置为 window(它将是未定义的) )。
  • @RobG 是的,在严格模式下,fn(); 时这将是未定义的
【解决方案2】:

让我们稍微扩展一下你的代码:

var length = 20;
function fn() {
    console.log(this, this.length);
}

var o = {
    length: 10,
    e: function(fn) {
        fn();
        fn.call(this);
        arguments[0]();
    }
}

o.e(fn);​

演示:http://jsfiddle.net/ambiguous/Ckf2b/

现在我们可以在调用fn 时看到this 是什么(以及this.length 的来源)。这给了我以下输出:

DOMWindow 0
Object 10
[function fn() { console.log(this, this.length); }] 1

我们还有三种调用函数fn的方式:

  1. fn(): 就像任何旧函数一样调用它。
  2. fn.call(this):使用 call 强制指定上下文(AKA this)。
  3. arguments[0]():通过arguments对象调用fn

当您说fn() 时,在任何地方都没有this 的显式值,因此,在浏览器中,您将window 作为您的this。全局window恰好有一个length property

返回窗口中的帧数(frame 或 iframe 元素)。

这就是零(在我的输出中)的来源,您的 window.length 可能不同。

我们将e 称为o.e(fn),所以thise 中是o,这就是o.e(...) 的含义(排除绑定函数和相关的复杂性)。因此fn.call(this) 中的thiso,这使得fn.call(this)o.fn = fn; o.fn() 相同(或多或少),我们在控制台中得到o10。注意到那个点又出现了吗?

fn.call(o) 就像o.fn = fn; o.fn()

第三个arguments[0]() 包含一个隐藏点,因为p = 'm'; o[p] (或多或少)与o.m 相同,所以arguments[0]() 类似于fn = arguments[0]; arguments.fn = fn; arguments.fn()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 2016-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多