在哈希对象上调用forEach

时间:2014-12-20 21:20:57

标签: javascript

所以,这有效(至少在chrome中):

var foo = {
    0: 'a',
    1: 'b',
    2: 'c'
};

//add a non-enumerable length property
Object.defineProperty(foo, 'length', {value: 3});

[].forEach.call(foo, function(val){console.log(val);}); //logs a b c

如果键是数字字符串而不是整数,它甚至可以工作,只要有一个length属性。但是,如果键是非数字字符串,则它会无声地失败。如果某些键是数字的,有些键是否适用于数字键,而在其他键上无声地失败。所以我的问题是双重的。首先,为什么我不能用非数字字符串执行此操作(底层实现是否使用递增for循环?为什么它足够聪明,然后在键上进行类型强制?)

我的意思是,javascript没有真正的数组,对吧?它们只是用整数作为键的哈希表查找?因此,尽管我意识到我在这里将语言扩展到了突破点,为什么不能以正确的多态方式实现/破解这种行为呢?

第二个问题是,如果不应该/能够使其工作,谁认为让它失败默默是个好主意?为什么这不会引发错误?

1 个答案:

答案 0 :(得分:1)

它仅适用于0length之间的整数键,因为Array.prototype.forEach应该与类似数组的对象一起使用。

底层实现是否使用递增for循环?

或多或少。其行为在ES5 Section 15.4.4.18

中定义
  
      
  1. O成为调用ToObject传递此值作为参数的结果。
  2.   
  3. lenValue成为使用参数“[[Get]]”调用O length内部方法的结果。
  4.   
  5. len成为ToUint32(lenValue)
  6.   
  7. 如果IsCallable(callbackfn)false,则抛出TypeError例外。
  8.   
  9. 如果提供了thisArg,请TthisArg;其他请Tundefined
  10.   
  11. k成为0
  12.   
  13. 重复,同时k < len   
        
    1. Pk成为ToString(k)
    2.   
    3. kPresent成为使用参数[[HasProperty]]调用O Pk内部方法的结果。
    4.   
    5. 如果kPresenttrue,那么   
          
      1. kValue成为使用参数[[Get]]调用O Pk内部方法的结果。
      2.   
      3. 使用[[Call]]作为callbackfn值{和}参数列表,将T内部方法this称为kValuek和{ {1}}。
      4.   
    6.   
    7. O增加k
    8.   
  14.   
  15. 返回1
  16.   

为什么它适用于非数组对象?

它的设计表现如下:

  

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

为什么不为非数字属性调用forEach

非数字属性“失败”,因为callbackfn只是一个数组方法,其目的是迭代类似数组的对象。如果要迭代对象的所有属性,则应该使用forEach循环。