Javascript 为什么代码指向窗口对象?

Javascript 为什么代码指向窗口对象?,javascript,arguments,this,Javascript,Arguments,This,我的代码是: var length = 20; function fn(){ console.log(this.length); } var o = { length:10, e:function (fn){ fn(); arguments[0](); } } o.e(fn); 输出是20,1,谁能告诉我为什么?当这个关键字出现在函数内部时,它的值取决于如何调用该函数 var length = 20; function fn(){

我的代码是:

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

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

o.e(fn);

输出是
20,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);
在您的情况下,调用
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
,可以使用
call
apply
,或
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);

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

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);​
演示:

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

DOMWindow 0
Object 10
[function fn() { console.log(this, this.length); }] 1
我们还有三种方法调用函数
fn

  • fn()
    :只需像调用任何旧函数一样调用它
  • fn.call(this)
    :用于强制特定上下文(AKA
    this
  • arguments[0]()
    :通过
    arguments
    对象调用
    fn
  • 当你说
    fn()
    时,任何地方都看不到
    this
    的显式值,因此,在浏览器中,你会看到
    窗口
    作为你的
    this
    。全局
    窗口正好有一个:

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

    这就是零(在我的输出中)的来源,您的
    窗口。长度可能不同

    我们把
    e
    称为
    o.e(fn)
    所以
    这个
    内部
    e
    o
    ,这就是
    o.e(…)
    的意思(禁止有界函数和相关的复杂性)。因此
    fn.call(this)
    中的
    this
    o
    ,这使得
    fn.call(this)
    o.fn=fn相同(或多或少);o、 fn()
    我们在控制台中得到
    o
    10
    。注意到那个圆点又出现了吗

    调用(o)
    类似于
    o.fn=fn;o、 fn()


    第三个变量,
    arguments[0]()
    ,包含一个隐藏点,名为
    p='m';o[p]
    o.m
    相同,因此
    arguments[0]()
    类似于
    fn=arguments[0];arguments.fn=fn;arguments.fn()

    阅读一下@muistooshort你说的
    fn()
    arguments[0]()
    ,一个调用
    call
    ,另一个调用
    apply
    ?在第一个调用中,你得到20个
    this==window
    ,在第二个
    this==arguments
    。将console.log更改为
    console.log(this.length,this)和调用
    o.e(fn,'test')
    和您看到的是arguments数组。@dbaseman:这些都是关于使用显式
    this
    执行
    fn()
    的。
    参数[0]()
    的行为是这样的,因为有一个隐藏点,所以有点像说
    参数.0()
    (当然,如果后者是有效的JavaScript)。
    这不是上下文,它是执行上下文(或ES5中的词汇环境)的一个组件。您应该编写调用
    fn()时没有提供此值的。调用
    this
    上下文会让人困惑。哦,如果代码处于严格模式,那么会抛出一个类型错误,因为如果没有提供值(它将是未定义的),它不会将
    this
    设置为
    window
    。@RobG Yes,在严格模式下,当do
    fn()时,这将是未定义的