在哈希对象上调用 forEach

Calling forEach on a hash object

本文关键字:调用 forEach 对象 哈希      更新时间:2023-09-26

所以,这有效(至少在 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

如果键是数字字符串而不是整数,它甚至可以工作,只要有一个长度属性。但是,如果键是非数字字符串,则会以静默方式失败。如果某些键是数字键,而某些键或非数字键适用于数字键,而在其他键上静默失败。所以我的问题是双重的。首先,为什么我不能用非数字字符串来做到这一点(底层实现是否使用递增for循环?为什么它足够聪明,可以对键进行类型强制?(

我的意思是,javascript没有真正的数组,对吧?它们只是以整数作为键的哈希表查找?因此,尽管我意识到我在这里将语言拉伸到临界点,但为什么不能实现/黑客攻击以适当的多态方式运行呢?

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

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

基础实现是否使用递增 for 循环?

或多或少。它的行为在 ES5 第 15.4.4.18 节中定义:

  1. O是调用ToObject传递 this 值作为参数的结果。
  2. 让我们lenValue调用[[Get]]内部方法的结果,O参数为"length"。
  3. len ToUint32(lenValue).
  4. 如果IsCallable(callbackfn) false,则抛出TypeError异常。
  5. 如果thisArg被提供,就T thisArg;否则就T undefined
  6. k 0.
  7. 重复,同时k < len
    1. Pk ToString(k).
    2. 让我们kPresent调用带有参数PkO[[HasProperty]]内部方法的结果。
    3. 如果kPresent true ,则
      1. 让我们kValue调用带有参数PkO[[Get]]内部方法的结果。
      2. 调用 [[Call]] 的内部方法callbackfnT 作为包含 kValuekOthis值和参数列表。
    4. k增加1
  8. 返回undefined .

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

它的行为是这样的设计:

forEach函数是有意泛型的;它不需要 它的这个值是一个数组对象。因此它可以是 转移到其他类型的对象以用作方法。是否 forEach函数可以成功应用于主机对象是 依赖于实现。

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

对于非数值属性,它"失败"forEach因为只是一个数组方法,其目的是迭代类似数组的对象。如果要迭代对象的所有属性,则应使用 for...in 循环。