对象那些事-属性的位置?

56 阅读2分钟

今天朋友给我发了个链接,是一道题,以为自己避开了所有缺陷,没有想到找到了个知识漏洞,蛮有意思的,记录一哈

let obj = {
  a:0
}
obj['1'] = 0
obj[++obj.a] = obj.a++
let values =Object.values(obj)
obj[values[1]] = obj.a
console.log(obj)

接下来来分析一下里面的每一句代码

obj['1'] = 0是给对象obj添加一个属性,那么添加的属性应该在a前还是a后呢?我们来打印一下

image.png

难道这个顺序是按照添加的顺序反向来的吗?其实也不是

let obj = {
  a:0
}
obj['1'] = 0
obj['2'] = 7
obj['b'] = 9
obj['aa'] = 17
obj['g'] = 2 
obj[true] = 11
obj[false] = 12
obj[Symbol()]=15
obj['c'] = 4
console.log(obj)
let values =Object.values(obj)
console.log(values)

image.png

看来它会把数字类的属性全部提前并按照升序排列,字母类的字符串也按照升序排好了,但是留意我们用Object.values(obj)获取到的所有属性值,返回的数组里面的顺序和obj对象中的不一致,Object.values() 的结果是数字类的字符串全部提前并升序排好,其他的按照添加顺序,以上是浏览器的执行结果,在node环境下,结果又不一样,不同的环境下可能会有不同的结果。嗯?excuse me?那我怎么知道这个东西是什么结果啊?开发中不会写出这种代码的吧(依靠对象的顺序或者Object.values()顺序进行操作let values =Object.values(obj); obj[values[1]] = obj.a),所以不用担心会写出什么bug,就是可能会遇到这种面试题,哎~

执行完obj['1'] = 0后,obj就变成了下图的样子

image.png

obj[++obj.a] = obj.a++,首先看=的左边,obj.a是0,++obj.a的返回值是1,=左边就是obj[1],此时的obj.a的值是1,右边的++obj.a是先使用obj.a的值赋值给左边后,再自+1,所以obj[1]的值是1,obj.a的值是2

感觉这里除了++的考点外还有一个对象的属性名称只能是字符串或者Symbol的考点,所以obj[1]obj['1']是一样的,如果这个知识点遗漏了,你的答案就是出现obj[1]和obj['1']两个属性的错误答案

image.png

let values =Object.values(obj)这句没什么说的,获取obj对象所有属性的value值,返回一个数组,执行以后的values的值是[1,2],现在知道为啥要搞明白新加的属性是在哪个位置了吧

obj[values[1]] = obj.a,实际上就是obj[2] = 2,执行完这条代码以后,obj就是 {1: 1, 2: 2, a: 2}

所以这道题的知识点有:

  1. 对象属性的位置
  2. a++和++a的区别
  3. Object.values()的返回值中的值顺序
  4. 对象的属性名称只能是字符串或者Symbol