【问题标题】:Calling forEach on a hash object在哈希对象上调用 forEach
【发布时间】:2014-12-20 21:20:57
【问题描述】:

所以,这有效(至少在 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 没有真正的数组,对吧?它们只是以整数作为键的哈希表查找?因此,尽管我意识到我在这里将语言延伸到了临界点,但为什么不能实现/破解它以以适当的多态方式表现呢?

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

【问题讨论】:

  • 你检查过this question吗?至于垫片,流行的库/框架中有很多;最简单的方法是在Object.keys 上使用forEach。
  • 你搞错了。 JavaScript 确实 有真正的数组,但它们被伪装成以字符串为键的对象。 JS 中没有“整数属性名”这样的东西。
  • 关于 javascript 没有真正的数组,对吗? 部分:嗯,有点像an overstatement。
  • @raina77ow:是的,我知道如何迭代哈希,我在问为什么它的行为方式是这样的,我不是很厉害擅长阅读语言规范文档。感谢您对 js 数组性质的澄清。你也是bergi,谢谢。
  • @bergi 那么这类似于 js 包装原语的方式吗?

标签: javascript


【解决方案1】:

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

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

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

  1. 让O 成为调用ToObject 并传递this 值作为参数的结果。
  2. 让lenValue 成为使用参数“length”调用O 的[[Get]] 内部方法的结果。
  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 成为使用参数Pk 调用O 的[[HasProperty]] 内部方法的结果。
    3. 如果kPresent 是true,那么
      1. 让kValue 成为使用参数Pk 调用O 的[[Get]] 内部方法的结果。
      2. 调用callbackfn的[[Call]]内部方法,将T作为this值和包含kValue、k和O的参数列表。
    4. 将k 增加1。
  8. 返回undefined。

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

它的行为是这样设计的:

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

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

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

【讨论】:

  • 好的,我知道了。我的小技巧只是因为我使用了与长度匹配的顺序数字键,forEach 只是从 0 循环到len - 1 转换为 str 并尝试访问对象上的该属性。它根本不适用于非顺序键。尽管您没有直接解决它,但它也解释了为什么没有抛出错误。乐叹息。返回Object.keys(obj).forEach()。
猜你喜欢
  • 2016-09-08
  • 1970-01-01
  • 2013-07-25
  • 2013-07-27
  • 2013-01-16
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 2012-05-02
相关资源
最近更新 更多