JS绑定函数和函数调用操作符的性质

时间:2014-09-01 16:31:32

标签: javascript oop

var obj = {};

var r1 = (obj['toString'])();
var m1 = obj['toString'];
var r2 = m1();

var r3 = (obj.toString)();
var m2 = obj.toString;
var r4 = m2();

r1r3预计会包含正确的结果:"[object Object]",而r2r4包含显示"[object Undefined]"的{​​{1}}并且m1不受约束。

我无法完全理解m2的执行方式。我总是这样看,obj['toString']() - > (obj['toString'])()。事实证明,函数调用操作符回顾什么是上下文。我希望操作员不知道操作数的来源。

任何人都可以正确解释这种行为吗?

3 个答案:

答案 0 :(得分:4)

  

事实证明,函数调用操作符会回顾上下文是什么。我希望操作员不知道操作数的来源。

事实上,它确实知道。

在EcmaScript规范中,property accessor operators(以及一些类似的操作)对此进行了描述,以返回一个“Reference object”,其中包含完整的信息:访问该属性的上下文。任何“正常”操作通常只会获得引用的值 - 包括assignment operators,它会在您的情况下解散引用。

call operator使用它来使方法调用特别:

  
      
  1. ref成为评估MemberExpression的结果。 可能会返回Reference
  2.   
  3. funcGetValue (ref)获取实际的函数对象 - 您在规范
  4. 中看到了很多这样的操作   
  5. ... 获取参数,执行某些类型的断言
  6.   
  7. 如果Type(ref)为Reference,那么   
        
    • 如果IsPropertyReference(ref)为真,那么
        让thisValueGetBaseref)。 < - 此处提取方法上下文
    •   
    • 否则,ref的基础是环境记录
        ... 基本上描述了with语句
    • 中的变量   
  8.   
  9. 否则,类型(ref)不是Reference   让thisValueundefined
  10.   

答案 1 :(得分:4)

这实际上是grouping operator (...)

的“特殊”行为
  

1。返回评估 Expression 的结果。这可能是参考类型。

     

注意此算法不会将GetValue应用于评估Expression的结果。这样做的主要动机是,deletetypeof等运算符可以应用于带括号的表达式。

因此,此运算符特别不调用GetValue,因此不会返回函数对象本身,而是返回整个引用,因此期望引用的操作仍然有效。


引用基本上是一个带有可选“基值”的值的封装,它是属性访问时的对象。

答案 2 :(得分:0)

"这个"似乎总是会引起JavaScript的混乱,特别是在回调等场景中。

稍微修改你的例子,因为你正在使用toString()而我们无法看到它的实现,我已经介绍了一个可以看作依赖于上下文的函数,这就是<强>此即可。编码器期望访问对象属性x,但是当函数未绑定时,他会感到惊讶。

window.x = "some global value";
var obj = { 
    wibble : function() { console.log("wibble " + this.x); }, 
    x : 7
};

obj.wibble();
var f = obj.wibble;
f();

这导致:

wibble 7 
wibble some global value

那时我们明确地以obj.wibble()或obj [&#34; wibble&#34;]的形式指定一个上下文,这个的行为就像大多数开发人员所期望的那样。

然而,当我们打电话给&#34;裸体&#34;函数,我们有效地得到一个默认上下文,在我的例子中,我碰巧在该上下文中有 x 的值,因此得到该值,恰好是一个字符串。