Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
允许'p.foo=o.foo'返回对函数'foo'的引用的javascript机制/规则是什么?_Javascript_Function_This_Indirection - Fatal编程技术网

允许'p.foo=o.foo'返回对函数'foo'的引用的javascript机制/规则是什么?

允许'p.foo=o.foo'返回对函数'foo'的引用的javascript机制/规则是什么?,javascript,function,this,indirection,Javascript,Function,This,Indirection,我目前正在学习javascript,学习《你不知道js》系列 在“this&objectprototype”一节中,在讨论“函数的间接引用”时,作者指出 赋值表达式p.foo=o.foo的结果值为 仅引用底层函数对象。因此 有效的调用站点只是foo(),而不是像您可能看到的p.foo()或o.foo() 期待。根据上述规则,默认绑定规则适用 显然,(p.foo=o.foo)返回对函数foo的引用。但是允许(p.foo=o.foo)返回对函数foo的引用的机制/规则是什么?换句话说,为什么简单赋值

我目前正在学习javascript,学习《你不知道js》系列

在“this&objectprototype”一节中,在讨论“函数的间接引用”时,作者指出

赋值表达式p.foo=o.foo的结果值为 仅引用底层函数对象。因此 有效的调用站点只是foo(),而不是像您可能看到的p.foo()或o.foo() 期待。根据上述规则,默认绑定规则适用


显然,
(p.foo=o.foo)
返回对函数
foo
的引用。但是允许
(p.foo=o.foo)
返回对函数
foo
的引用的机制/规则是什么?换句话说,为什么简单赋值返回对
foo
函数的引用

当我想理解这样的事情时,我发现一步一步地把它分解是很有帮助的

  • o.foo
    查看
    o
    对象并找到名为
    foo
    的属性。它返回对该属性的引用,不管它是什么。在这种情况下,
    o.foo
    属性是对函数
    foo
    的引用
  • p.foo=o.foo
    获取上面的结果(对函数
    foo
    的引用),在
    p
    对象中创建一个属性,该属性也被命名为
    foo
    。因此现在
    p.foo
    也是对
    foo
    函数的引用,与
    o.foo
    完全相同
  • 该表达式用括号括起来,因此现在您有了
    =
    符号或
    p.foo
    左侧的内容,它(作为提醒)仍然是对
    foo
    函数的引用
  • 现在我们在末尾找到
    ()
    。这将调用我们目前手头的任何函数。这就是
    foo
    函数。请特别注意,我们没有调用
    p.foo()
    。这将是对
    p.foo
    作为引用的函数的方法调用,因此在该函数中,
    this
    将设置为
    p
    。但我们没有这样做。我们只是调用
    (p.foo=o.foo)
    返回的任何函数。与以前一样,这是相同的
    foo
    函数,但现在我们已经失去了它与
    o
    对象或
    p
    对象的任何连接
  • 因此,当我们在最后进行调用时,我们只是调用
    foo
    函数,而没有对任何特定对象设置
    this
    。因此,当我们进行调用时,
    this
    被设置为
    undefined
  • 但是我们没有在
    严格的
    模式下运行,所以JavaScript“有益地”不想给我们一个未定义的
    this
    ,所以它将
    this
    设置为浏览器中的
    窗口
    对象或节点中的
    全局
    对象
  • 之前我们做了
    var a=2。因此
    窗口
    全局
    对象实际上现在有一个名为
    a
    的属性,该属性的值是
    2
  • 现在,当我们执行
    console.log(this.a)
    时,我们从
    窗口
    全局
    对象中选择
    a
    属性。该值为
    2
  • 如果所有这些代码都不是在全局级别运行的,而是在一个函数中运行的呢?那么会发生什么

    功能测试(){
    函数foo(){
    console.log(this.a);
    }
    var a=2;
    var o={a:3,foo:foo};
    var p={a:4};
    o、 foo();//3
    (p.foo=o.foo)(;//是2,但现在未定义
    }
    
    test()赋值运算符
    =
    是JavaScript中生成(返回)赋值的表达式。因为它是一个表达式,所以可以在任何允许表达式的地方使用,例如括号内

    例如:

    let test = (a = b = c = { name: 'test' })
    
    上面的代码首先计算括号中的表达式,并将变量
    c
    b
    a
    指向测试对象(按该顺序),然后将
    test
    指向该表达式产生的值。执行该行后,
    a
    b
    c
    test
    都将指向同一对象

    同样地

    (p.foo = o.foo)
    
    将产生
    o.foo
    返回(从技术上讲,它将产生
    o.foo
    指向的任何内容,即函数
    foo

    至于

    (p.foo = o.foo)()
    
    通过在parenths之后添加额外的
    ()
    ,我们告诉引擎我们想要调用表达式
    (p.foo=o.foo)
    最终生成的任何内容。因此,我们最终调用函数
    foo

    一个有用的重写方法是将上面的一行想象成这样:

    let produced = (p.foo = o.foo)
    produced()
    

    .

    我正要发布一个不完整的答案,基本上你的第8步不见了。谢谢你理解了我不太明白的地方。我知道这是
    窗口,但不知道为什么。向上投票:-)实际上,在步骤5中,
    这个
    被专门作为
    未定义的
    传递。第8步是不相关的-它与呼叫类型无关。在第6步中,sloppy mode函数将
    值强制转换为一个对象,并用全局对象替换
    null
    未定义的
    。@CaptainAmerica是的,它们是相同的。在这两种情况下,您都得到了对
    foo
    函数的引用,然后直接将其作为函数调用,而不是作为方法调用。@CaptainAmerica多年的StackOverflow经验:-)我将重新措辞:如果最后一行是
    var q=o.foo,理解起来会不会更简单;q();//2
    ?这意味着
    o.foo
    返回
    foo()
    ,并将
    q
    转换为一个代理,而不带括号
    let produced = (p.foo = o.foo)
    produced()