【问题标题】:Symbol.iterator: get all the object's properties in iterator objectSymbol.iterator:获取迭代器对象中所有对象的属性
【发布时间】:2017-12-19 12:22:13
【问题描述】:

我目前正在阅读有关Symbols and Iterators(ES6 功能)的信息,在遇到一个示例之后,我正在尝试使对象可迭代,以便我可以使用for...of 功能。从这里的几个例子/答案/我检查的文章中,它看起来像这样:

let obj = {
  prop1: 5,
  prop2: 'test',
  prop3: new Date(),
  [Symbol.iterator]: () => ({
  items: obj.items,
  next: function next() {
    return {
        done: this.items.length === 0,
        value: this.items.shift()
      }
  }
  })
};
Object.defineProperty(obj, "items", {
  enumerable: false,
  get: function() {
      let props = [];
      for(let prop in this) if(this.hasOwnProperty(prop)) props.push(this[prop]);
      return props;
  }
});
for(let prop of obj) console.log(prop);

但我发现手动列出 items 迭代器数组中对象属性的所有值很烦人。 Object.defineProperty 也让人感觉又脏又乱。我有点想从link 扩展示例。是否有更智能/更简单的方法来获取迭代器中的所有对象属性(而不是 items: obj.items 和相关的膨胀或手动列出像 items: [5, 'test', new Date()] 这样的项目)?

【问题讨论】:

  • 你为什么认为你需要一个 .items getter 属性来做这个?
  • 好吧,首先,我需要设置enumerable: false 以避免此属性本身出现在列表中;也可以使物体更干净。
  • 不要让对象可迭代,没有意义。相反,只需写 for (let prop in obj) console.log(prop); - 这就是 for … in 循环的好处!
  • 不,你为什么认为你需要obj.items
  • 我需要它来获取迭代器方法的实际值数组。

标签: javascript ecmascript-6 iterator symbols


【解决方案1】:

你可以在符号迭代器中返回一个生成器:

[Symbol.iterator]:function*(){
    for(value of Object.values(this)){
      yield value;//may extend this to your needs
    }
 }

或者在你的情况下:

[Symbol.iterator]:function*(){
  var i=1;
  while(this["prop"+i]){
      yield this["prop"+i];//may extend this to your needs
      i++;
  }
}

http://jsbin.com/zekunalusi/edit?console

【讨论】:

  • 这会在of 尝试迭代对象时创建无限递归......
  • @bergi 哦,对了,Object.values() 是否使用迭代器(我希望不是)?
  • 那行,Object.values 枚举属性
  • 我尝试了您的第二种选择。它说Uncaught ReferenceError: regeneratorRuntime is not defined
  • 对不起,它适用于 jsbin,但在我测试的 codepen 上失败
【解决方案2】:

您不应使用items getter,而应在迭代器方法中创建数组。您也可以使用生成器语法来创建迭代器,这要容易得多。

但实现你想要的最简单的方法是

let obj = {
  prop1: 5,
  prop2: 'test',
  prop3: new Date(),
  [Symbol.iterator]() { return Object.keys(this).map(k => this[k])[Symbol.iterator](); }
};

【讨论】:

  • 当我用for..of 尝试这个时,我得到了Object.values(...).values is not a function 错误。
  • 哦,对了,Object.values 仍处于试验阶段。我会更新
  • 现在显示Uncaught TypeError: Object.keys(...).map(...).values is not a function
  • @curveball 显然,由于兼容性问题,浏览器落后于支持values。幸运的是,相同的方法以不同的名称存在:-)
【解决方案3】:
function objectEntries(obj) {
    let index = 0;

    // In ES6, you can use strings or symbols as property keys,
    // Reflect.ownKeys() retrieves both
    let propKeys = Reflect.ownKeys(obj);

    return {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            if (index < propKeys.length) {
                let key = propKeys[index];
                index++;
                return { value: [key, obj[key]] };
            } else {
                return { done: true };
            }
        }
    };
}

let obj = { first: 'Jane', last: 'Doe' };
for (let [key,value] of objectEntries(obj)) {
    console.log(`${key}: ${value}`);
}

http://2ality.com/2015/02/es6-iteration.html

【讨论】:

    猜你喜欢
    • 2013-07-14
    • 2021-10-09
    • 2023-03-24
    • 2016-02-26
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多