对象的属性值计算问题

const obj = {a: 1}
obj["a"] = obj["a"]++
obj // {a: 1}

我理解先是执行 obj['a'] = obj['a'], 但是 obj 是一个对象,再执行 obj['a']++ 为什么不奏效呢?

阅读 3k
5 个回答

首先要知道 js 对象中的 [[Get]] 和 [[Put]] 操作

我们重新定义一下obj对象中对属性agettersetter
在每次读取和写入时打印一下obj.a的值。

var obj = {
  _a: 1,
  get a() {
    console.log(`get a = ${this._a}`)
    return this._a;
  },
  set a(num) {
    console.log(`set a = ${num}`);
    this._a = num;
  }
}

然后我们执行问题中的操作:
obj["a"] = obj["a"]++
控制台可以看到输出:

QQ20200301-202952@2x.png

可以看出obj.a实际上是读入之后改变后又被修改回来了。

如果学习过《深入理解计算机系统》,对寄存器有了初步了解的话你现在应该猜到这个过程应该是怎样的。

大概是这样(cpp 例子):

    movl    $1, -4(%rbp)
    movl    -4(%rbp), %eax
    leal    1(%rax), %edx
    movl    %edx, -4(%rbp)
    movl    %eax, -4(%rbp)
    movl    $0, %eax
    popq    %rbp

栈中-4(%rbp)当作obj.a,%edx%eax是寄存器,可以看出:
1.把obj.a + 1写入edx然后edx写入oxj.a这就是obj.a++的过程。
2.然后把eax写入obj.a,这就是赋值的过程,而值并没有变。

为什么 1+2*3 算出来不是9呢

赋值的优先级比较低,先++。然后赋值。

这个就是i++++i的区别:

const i = 0;
console.log(i++); // 0
const i = 0;
console.log(++i); // 1

所以你的代码中obj['a'] = obj['a']++等同于

let i = 0;
i = i++;

// ------- 类似伪代码:
i = 0
tmp = i
i = i + 1 // i++
i = tmp // i=

具体计算机的操作,可以尝试着去理解下对应的汇编,寄存器、栈什么的我也是一知半解的,但原理好像就是上面的伪代码

对上边++a和a++的补充

const obj = {a: 1}
obj["a"]++
obj // {a: 2}

还不如直接这样呢

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题