修改一个对象的循环行为

时间:2018-03-02 08:45:07

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

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

我正在为'iterable'(我为我的目的定义为Object,Array,Map或Set)中的'深度提取'值创建一个小实用程序。

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

可以这样做吗?

1 个答案:

答案 0 :(得分:3)

嗯,你可以做这样的事情(关于全局原型的常见警告):



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))