JavaScript ES6:如何使用[Symbol()]名称

时间:2018-03-05 15:18:20

标签: javascript

我正在试图弄清楚如何迭代使用Symbol名称来唯一标识属性的对象。例如,如果我有这个对象:

   const bowl1 = {
     'apple': { color: 'red', weight: 136.078 },
     'banana': { color: 'yellow', weight: 183.151 },
     'orange': { color: 'orange', weight: 170.097 },
     'peach': { color: 'yellow', weight: 176.845 }
   };

   for (var fruit in bowl1) {
       var item = bowl1[fruit];
       console.log(`${fruit}: `, item);
   }

   OUTPUT:
   apple:  { color: 'red', weight: 136.078 }
   banana:  { color: 'yellow', weight: 183.151 }
   orange:  { color: 'orange', weight: 170.097 }
   peach:  { color: 'yellow', weight: 176.845 }

   // can even write your own iterator to get the same results
   function* iterate_object(o) {
      var keys = Object.keys(o);
      for (var i = 0; i < keys.length; i++) {
         yield [keys[i], o[keys[i]]];
      }
   }

   // output is the same as above
   for (var [key, val] of iterate_object(bowl1)) {
      console.log(key, val);
   }

但是,如果我将此对象更改为使用符号:

   const bowl = {
     [Symbol('apple')]: { color: 'red', weight: 136.078 },
     [Symbol('banana')]: { color: 'yellow', weight: 183.15 },
     [Symbol('orange')]: { color: 'orange', weight: 170.097 },
     [Symbol('banana')]: { color: 'yellow', weight: 176.845 }
   };

请注意,符号用于防止第二个香蕉覆盖第一个香蕉。

无论如何,上面使用的方法都不会在此对象上正确迭代。

有没有办法使用Symbol名称迭代对象? 是否需要将其创建为类并具有迭代器方法?

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

您无法获取符号属性名称,因为它们不会存储为典型的字符/字符串值,但您可以遍历Object.getOwnPropertySymbols返回的列表并使用它们从对象中提取信息。 / p>

const bowl = {
     [Symbol('apple')]: { color: 'red', weight: 136.078 },
     [Symbol('banana')]: { color: 'yellow', weight: 183.15 },
     [Symbol('orange')]: { color: 'orange', weight: 170.097 },
     [Symbol('banana')]: { color: 'yellow', weight: 176.845 }
   };
   
for(let sym of Object.getOwnPropertySymbols(bowl) ) {
   console.log(bowl[sym]);
}

答案 1 :(得分:0)

如上所述,您无法获取符号属性名称,因为它们不会存储为典型字符串。但是,MDN站点确实说“另外,Object.getOwnPropertyNames()不会返回符号对象属性,但是,您可以使用Object.getOwnPropertySymbols()来获取这些属性。”

因此,为了获取有关对象的信息,请使用Object.getOwnPropertySymbols:

for(let sym of Object.getOwnPropertySymbols(bowl) ) {
    console.log(sym, bowl[sym]);
   }

输出:

   Symbol(apple) { color: 'red', weight: 136.18 }
   Symbol(banana) { color: 'yellow', weight: 183.15 }
   Symbol(orange) { color: 'orange', weight: 170.97 }
   Symbol(banana) { color: 'yellow', weight: 176.84 }

正如您所看到的,您没有将符号名称作为字符串,但它将返回符号及其引用的对象。

如果要将符号转换为字符串并只看到属性名称,则必须做一些额外的工作。

for(let sym of Object.getOwnPropertySymbols(bowl) ) {
      // remove the 'Symbol (' from string
      let symStr = String(sym).substring(7);

      // now lop off the last char ')'
      symStr = symStr.slice(0, -1);

      console.log(symStr, bowl[sym]);
   }

输出:

   apple { color: 'red', weight: 136.18 }
   banana { color: 'yellow', weight: 183.15 }
   orange { color: 'orange', weight: 170.97 }
   banana { color: 'yellow', weight: 176.84 }

如果需要,您可以在一行上组合字符串函数。

let symStr = String(sym).substring(7).slice(0, -1);

可能不是符号的最佳用途,并且有全局和本地符号。上面使用的示例来自课程材料是本地的。

答案 2 :(得分:0)

共有两种方法,将其共享以供参考,

const bowl = {
[Symbol('apple')]: { color: 'red', weight: 136.078 },
[Symbol('banana')]: { color: 'yellow', weight: 183.151 },
[Symbol('orange')]: { color: 'orange', weight: 170.097 },
[Symbol('banana')]: { color: 'yellow', weight: 176.845 }
};

const bowlReflect = Reflect.ownKeys(bowl);
const ownPropertySymbols = Object.getOwnPropertySymbols(bowl);

**Method:1**
for(const fruit of bowlReflect){
 console.log(bowl[fruit])
 }

Method:2
for(const fruit of ownPropertySymbols){
 console.log(bowl[fruit])
}