在forEach的官方实现中,“var t = Object(this)”有什么意义?

时间:2011-06-27 20:21:41

标签: javascript

According to the MDC,ECMA-262,第5版将forEach实施为:

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in t)
      fun.call(thisp, t[i], i, t);
    }
  };
}

有人能告诉我“var t = Object(this)”这行是做什么的吗?对象(这个)与普通的不同之处是什么?在这里做的差异是什么工作?

3 个答案:

答案 0 :(得分:16)

Mozilla实现只是尝试模拟规范中描述的步骤,Object(this);模拟第一步,调用ToObject内部方法:

来自Array.prototype.forEach 15.4.4.18

  

...

     

调用forEach方法时   一个或两个参数,如下   采取的步骤:

     
      
  1. 让O成为召唤的结果   ToObject传递此值作为   参数。

  2.   
  3. 让lenValue成为使用参数“length”调用O的[[Get]]内部方法的结果。

  4.   
  5. 设len为ToUint32(lenValue)。

  6.         

    ...

在幕后调用the Object constructor as a function内部进行类型转换,如15.2.1.1中所述调用ToObject方法。

如果你仔细观察,还有更多这样的事情,例如,行:

var len = t.length >>> 0;

他们使用无符号右移运算符(ToUint32)模拟对>>>内部方法的调用,如步骤3中所述。

修改 前面的行回答了为什么 Mozilla实现以这种方式实现它。

你可能想知道为什么ECMAScript规范。我需要致电ToObject,查看第2步,这看起来很明显:

  
      
  1. 让lenValue成为使用参数“length”调用O的[[Get]]内部方法的结果。
  2.   

规范。需要确保调用函数时使用的this值是一个对象,因为原始值没有任何内部方法,正如您在步骤2中看到的那样,需要[[Get]](P)内部方法来获取length属性的值。

这样做是因为对于严格函数(以及内置函数),您可以将原始值设置为函数的this值,例如:

(function () {"use strict"; return typeof this; }).call(5); // "number"

对于非严格函数,this值始终转换为Object:

(function () { return typeof this; }).call(5); // "object"

答案 1 :(得分:3)

可能的原因是s9.9 ECMA-262,关于抽象 ToObject 操作(如@CMS所述)。

nullundefined值被调用时,它会强制抛出TypeError,但这些已被前一行捕获。

但是如果你打电话:

Array.prototype.forEach.call("123", func() { ... } )
如果不是类型强制,这将失败。特别是如果index in thisthis,则您无法致电string,但可以 ToObject的结果上调用它

15.4.4.18中的这段文字可能很重要:

  

forEach函数是故意通用的;它不要求它的这个值是一个Array对象。因此,它可以转移到其他类型的对象以用作方法。 forEach函数是否可以成功应用于宿主对象是依赖于实现的。

答案 2 :(得分:0)

我一直在写var t = this;。我发现它的范围有时依赖于浏览器;在任何情况下,当范围发生变化时,并不总是清楚浏览器将使用关键字做什么,特别是在方法闭包中。我喜欢将我的JS代码愚蠢到幼儿园级别,为个人浏览器留下最小的空间来做奇怪的事情。

为了确保在将this传递给某个方法或其他内容时,我总是要处理我想要处理的this,我总是先写var t = this;作为第一个我的方法的一行。然后,t是一个变量并遵循可预测的变量范围规则,并且在指定时将其指针分配给此时由此表示的对象。这样我就不必担心方法,其他对象或不合规的浏览器重新解释this在范围内引用的内容。