对象成员函数的{javascript函数调用表达式

时间:2015-09-17 04:02:12

标签: javascript

我试图了解对象成员函数何时绑定到对象实例。在以下示例中

function F() {
  this.foo = 'foo';
};

var f = new F();
f.test = function() {
  alert(this.foo);
};

var c = f.test;


f.test();
(f.test)();
var d;
(d = f.test)();
c();    

输出为"foo""foo"undefinedundefined(正如预期的那样)。如果我们查看最后4行的AST,它看起来像this,并且与直接调用和赋值+ call

相同的MemberExpression参数
{
  "type": "MemberExpression",
  "computed": false,
  "object": {
      "type": "Identifier",
      "name": "f"
  },
  "property": {
      "type": "Identifier",
      "name": "test"
  }
}

所以问题是:为什么我们不能将(f.test)()读作两个不同的操作 - MemberExpression + CallExpression,而是看起来更像是“MemberCallEcpression”语言中的特殊情况(以及为什么AST解析器不会有它作为特例)?为什么f.foo表达式的结果是函数调用的绑定函数和赋值的未绑定函数?

1 个答案:

答案 0 :(得分:0)

括号充当语法分组机制,但它们在表达式的语义解释/评估中不做任何事情。因此,在带括号的表达式中,括号内的任何内容都保存在之前的点,从子表达式中检索该值。这意味着属性引用子表达式保持在正确的状态,这样当最终提取该值时,操作就会发生,就好像括号根本不存在一样。

编辑 - 正如RobG在几条评论中指出的那样,关键在于语言定义定义评估表达式的过程。该规范将评估所涉及的步骤与可能以获得与操作符一起使用的实际值的步骤区分开来,以及实际获得值的步骤。在这些术语中,( )令牌实际上不是运算符,而.[ ]=之类的是GetValue令牌。因此,为了参与执行操作员的行为,必须进行.概念操作。此时,如果值的来源是[]this的结果,则该事实已知,并且将发生“方法调用”=行为。然而,价值本身并没有任何来自它的“记忆”。如果该值用于执行类似 $(document).ready(function(){ $(".chk-message16").hide(); var Onee = $("#one, #two, #three, #four"); Onee.on('change', function() { if($('input[type=checkbox]:checked').length == 4){ $(".chk-message16").show(); }else{ $(".chk-message16").hide(); } }); });(赋值)的行为或用作函数调用参数,则对该值的未来操作将不会“记住”该值是从对象获取的物业参考。

我很自然地承认,这很奇怪。