代码之家  ›  专栏  ›  技术社区  ›  Thor

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

  •  3
  • Thor  · 技术社区  · 8 年前

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

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

    function 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
    

    赋值表达式p.foo=o.foo的结果值为 仅引用底层函数对象。因此 有效的调用站点只是foo(),而不是像您可能的那样p.foo()或o.foo()

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

    2 回复  |  直到 8 年前
        1
  •  2
  •   Michael Geary    8 年前

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

    1. o.foo 看看 o foo 。它返回该属性的引用,不管它是什么。在这种情况下 o、 傅 属性是对函数的引用 .
    2. p.foo = o.foo ),在 p p.foo 也是对 功能,与 .
    3. 这个表达式用括号括起来,所以现在你得到了 = 签名,或 p、 傅 作用
    4. 现在我们找到了 () 作用特别注意,我们是 使命感 p.foo() 。这将是对函数的方法调用 this 将设置为 p .但我们不会这么做。我们只是调用 ( p.foo = o.foo ) .和以前一样,这是相同的 功能,但我们现在已经失去了它与 对象或 p 对象
    5. 设置为 undefined
    6. 但我们不会跑进去 strict ,因此设置 window 浏览器中的对象或 global 节点中的对象。
    7. 之前我们做过 var a = 2; 全球的 对象实际上现在有一个名为 a 2
    8. 所以现在当我们做 console.log(this.a) ,我们拿起 来自 对象该值为 2.

    如果所有这些代码都不是在全局级别运行,而是在一个函数中运行呢?那么会发生什么?

    function test() {
      function 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)(); // was 2, but now is undefined
    }
    
    test();

    现在当我们打电话的时候 console.log( this.a ); , 仍然是指 全球的 对象但是当我们设定 var a=2; ,我们不再设置全局属性。我们只是创建一个局部变量。 window.a global.a 未定义

    严格模式避免了一些这种奇怪之处。如果我们放一个 'use strict'; 在代码的顶部,它将以严格模式编译。现在,当我们在最后进行最后一次函数调用时,我们在这里调用 函数(同样不是作为方法!), 现在设置为 未定义 控制台日志(this.a) 未定义 未定义

    让我们试试:

    'use strict';
    
    function 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)(); // was 2 in the original, but now throws an exception

        2
  •  1
  •   nem035    8 年前

    赋值运算符 =

    例如:

    let test = (a = b = c = { name: 'test' })
    

    上面的代码将首先计算括号中的表达式并指向变量 c b a 指向测试对象(按该顺序),然后它将指向 test , b c 都指向同一个对象。

    (p.foo = o.foo)
    

    将产生 o.foo 回来(从技术上讲,它会生产任何东西 是指向,这是函数 foo ).

    远至

    (p.foo = o.foo)()
    

    () (p.foo = o.foo) 最终产生了。因此,我们最终调用该函数 Similar patterns is used in IIFEs .

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

    Further reading about statements vs expressions .