【问题标题】:Modify an object's for...of loop behavior修改对象的 for...of 循环行为
【发布时间】:2018-08-10 10:56:15
【问题描述】:

鉴于 ES6 中新的“符号”原语,是否可以修改/设置对象中 for...of 循环的行为?

我正在创建一个小实用程序,用于从“可迭代”(出于我的目的将其定义为对象、数组、映射或集合)中的“深度提取”值。

Array、Map 和 Set 使用 for..of 循环,但普通对象不使用。为了保持一致性,我希望对象使用这个循环(并且应该迭代值而不是属性(因为 for...in 允许你这样做))。

这个可以吗?

【问题讨论】:

  • Given the new 'Symbol' primitive in ES6, is it possible to modify/set the behavior of a for...of loop in an object? 两者有什么关系?我迷路了
  • @JaromandaX Symbol 扩展了元编程的能力,我认为这可能是解决这个问题的关键(例如通过修改 Symbol.iterator)
  • 符号不能被修改 - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - 哦,等等,我想我理解你所说的修改 Symbol.iterator 的意思......
  • 是的,我应该更准确。通过“修改Symbol.iterator”,我的意思是修改绑定到对象上此属性的生成器函数(例如,可以在此处看到:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

标签: javascript ecmascript-6 for-of-loop


【解决方案1】:

好吧,你可以做这样的事情(关于全局原型的通常警告适用):

Object.prototype[Symbol.iterator] = function* () {
    yield* Object.values(this);
};

x = {a: 1, b: 2}

for (let y of x)
    console.log(y)

Object.defineProperty(
    Object.prototype,
    Symbol.iterator, {
        value: function*() {
            yield* Object.values(this);
        }
    }
);

myObj = {x: 1, y: 2}
console.log([...myObj])

但是,更简洁的解决方案是引入一个通用包装器,该包装器可以对本身不可迭代的对象进行迭代:

let iter = function* (a) {
    if (a === null || a === undefined)
        return;

    if (!a[Symbol.iterator]) {
        if (typeof a === 'object')
            a = Object.values(a);
        else
            a = [a];
    }

    for (let x of a)
        yield x;
};

console.log([...iter('abcd')])
console.log([...iter(123)])
console.log([...iter({a: 1, b: 2})])

然后只需在您的代码中使用for (x of iter(whatever))

【讨论】:

  • 快速提问:为什么您的第一个解决方案(直接修改 Object.prototype)有效,但 Object.defineProperty(Object.prototype, Symbol.iterator, { value: function*() { ... } }) 无效?
  • IIRC, defineProperty 在第二个参数上强制执行 toString
  • 嗯.. 似乎符号属性可以用 Object.defineProperty() - stackoverflow.com/questions/31029612/… 定义
  • @sookie:是的,我错了,实际上工作正常(见更新)。
猜你喜欢
  • 2015-07-05
  • 2020-07-10
  • 2017-02-08
  • 2020-01-14
  • 2016-04-25
  • 1970-01-01
  • 2019-08-23
  • 1970-01-01
  • 2020-10-14
相关资源
最近更新 更多