【Web前端问题】同一数据Object.keys,Object.values和Object.entries获得的个数不同
同一数据Object.keys,Object.values和Object.entries获得的个数不同
使用localStorage
localStorage.setItem(`0`,`你好`);localStorage.setItem(`1`,`再见`);
localStorage.setItem(`2`,`byb`);
localStorage.setItem(`name`,`nono`);
console.log(Object.keys(localStorage));
console.log(Object.values(localStorage));
console.log(Object.entries(localStorage));
console.log(`---------`);
for(var a in localStorage){
console.log(localStorage[a]);
}
输出结果:
设置自定义对象
let obj = {}; Object.defineProperties(obj, {
"0": {
value: `你好`,
enumerable:false
},
"1": {
value: `再见`,
enumerable:false
},
"2": {
value: `byb`,
enumerable:false
},
"name": {
value: `nono`,
enumerable:true
},
"length": {
value: 4,
enumerable:false
}
});
console.log(Object.keys(obj));
console.log(Object.values(obj));
console.log(Object.entries(obj));
console.log(`---------`);
for (var a in obj) {
console.log(obj[a]);
}
输出结果:
回答:
我在 Chrome 中测试,Object.keys
和 Object.values
Object.entries
返回的数量是一样的,都是 4 个。
本来我猜测,可能题主用的是 polyfill 非标准实现,或者是浏览器早期的不规范实现。但是,
- 通过
Object.getOwnPropertyDescriptor
可以发现,设置过的 item 的可枚举性始终为true
,而与propertyIsEnumerable
检测的结果不一致(使用propertyIsEnumerable
时,只有 name 是数字,而且是标准书写形式的整数时才会true
,其它都会false
),但for/in
时却都能枚举出来; - 另外,如果尝试用
localStorage.setItem
来设置length
getItem
setItem
__proto__
这些 name,那么localStorage.getItem
读取时倒还正常,直接访问对象属性时情况就非常混乱了。凡是setItem
过的都会被枚举出来,但取得的值却是原型链中的值(如果原型链中存在,不论是否原生,也不论在setItem
之前或之后添加)。
综上可见,localStorage
的可靠读取方式是 localStorage.getItem(name)
,直接 localStorage[name]
读取只是一种便捷用法,实现非常不可靠,很可能语言标准中都没具体规定,宿主是看着办的,就算规定了这情况也太曲折了。这非常类似于用 new Proxy
自行实现的对象,内部返回非常不统一。
简单来说,
- 出问题是
localStorage
使用方式的锅,getItem
的方式始终是稳定的,不应当把这个 API 看作是一个普通对象来用; - 枚举性不统一,是
localStorage
实现的锅,或Object.getOwnPropertyDescriptor
、propertyIsEnumerable
、for/in
实现的锅,因为结果不应当不同; Object.keys
Object.values
Object.entries
结果长度不一致,一定是此三者实现的锅,因为无论处理的奇葩是什么,它们三个都不应该长度不一样。
回答:
并非不同,是你那该死的极差的编码风格倒置 es 跟你开了个玩笑。
Object.values
、Object.entries
相比较 Object.keys
有一个不同,那就是 keys
只需要遍历对象即可,而前者还需要获取值。
这一过程就存在一个 IsPropertyKey
的判断,而这个判断的标准是 key
必须是字符串类型或Symbol类型才算是一个认可的属性名。
可你好死不死,非要取个 0
、1
才爽。具体在遍历一个 Storage
类型时是怎么样,我就不是很清楚了。
不过,此一问题,你可以换成这样:
localStorage.setItem(`funk0`,`你好`);localStorage.setItem(`funk1`,`再见`);
localStorage.setItem(`funk2`,`byb`);
localStorage.setItem(`name`,`nono`);
console.log(Object.keys(localStorage));
console.log(Object.values(localStorage));
console.log(Object.entries(localStorage));
console.log(`---------`);
for(var a in localStorage){
console.log(localStorage[a]);
}
世界又正常了!
Happy coding!
回答:
localStorage.propertyIsEnumerable("1") //falselocalStorage.propertyIsEnumerable("name") //true
可能localStorage.setItem 第一参能视为数字的情况下则不可枚举
以上是 【Web前端问题】同一数据Object.keys,Object.values和Object.entries获得的个数不同 的全部内容, 来源链接: utcz.com/a/143322.html