当前位置: 首页 > 科技观察

说说JS中Object的Key是无序的?

时间:2023-03-20 19:05:01 科技观察

初学JavaScript时,总是被灌输Object中的Key是无序不可靠的,而Map实例维护的是键值对的插入顺序。“但是,Object的键值对真的是无序的吗?”事实上,在ES2015之后,Object.keys的规则发生了变化:在一些现代浏览器中,keys的输出顺序是可以预测的!Keys都是Naturalnumber:注意这里的自然数指的是正整数或者0,如果是其他类型的Number——浮点数或者负数——会去下一组类型,比如NaN或者Infinity自然会被归入下一类。但是科学记数法有点特殊,有兴趣的同学可以自己尝试一下。综上所述,如果当前key是自然数,则按照自然数的大小升序排序。constobjWithIndices={23:23,'1':1,1000:1000};console.log(Reflect.ownKeys(objWithIndices));//["1","23","1000"]console.log(Object.keys(objWithIndices));//["1","23","1000"]console.log(Object.getOwnPropertyNames(objWithIndices));//["1","23","1000"]包含在for-in循环的遍历中,key也是按照这个顺序执行的。Key都是String:如果key不是自然数String(Number也会转成String),则按照加入的时间顺序排序。constobjWithStrings={"002":"002",c:'c',b:"b","001":"001",}console.log(Reflect.ownKeys(objWithStrings));//["002","c","b","001"]console.log(Object.keys(objWithStrings));//["002","c","b","001"]console.log(Object.getOwnPropertyNames(objWithStrings));//["002","c","b","001"]KeysaresymbolconstobjWithSymbols={[Symbol("first")]:"first",[Symbol("second")]:"second",[Symbol("last")]:"last",}console.log(Reflect.ownKeys(objWithSymbols));//[Symbol(first),Symbol(second)),Symbol(last)]console.log(Object.keys(objWithSymbols));//[Symbol(first),Symbol(second),Symbol(last)]console.log(Object.getOwnPropertyNames(objWithSymbols));//[Symbol(first),Symbol(second),Symbol(last)]如果key都是symbol,顺序和String一样,也是按照相加的顺序排序。如果是以上类型的组合constobjWithStrings={"002":"002",[Symbol("first")]:"first",c:"c",b:"b","100":"100","001":"001",[Symbol("second")]:"second",}console.log(Reflect.ownKeys(objWithStrings));//["100","002","c","b","001",Symbol(first),Symbol(second)]结果先按自然数升序排序,再按加入非数字字符串的时间排序,再按排序到Symbol的时间顺序,也就是说会先按照上面的分类进行拆分,先按照自然数、非自然数、Symbol的顺序排序,再按照上面的内部顺序排序三种。Recap在ES6之前,Object的键值对是无序的;ES6之后,Object的key-value对按照自然数、非自然数和Symbols进行排序。自然数按大小升序排序,另外两个按插入时间的顺序排序。参考资料:《PropertyorderispredictableinJavaScriptobjectssinceES2015》:https://www.stefanjudis.com/today-i-learned/property-order-is-predictable-in-javascript-objects-since-es2015《遍历ES6中对象属性的顺序”:http://2ality.com/2015/10/property-traversal-order-es6.html#traversing-the-own-keys-of-an-object