JavaScript 引用类型赋值与属性访问的执行顺序详解

作者:函数茶馆时间:2026-10-29 08:24:44浏览:372

本文深入解析JavaScript中引用类型赋值的执行细节。通过a.x = a = {n:2}这一经典案例,阐明赋值运算从右向左与点运算符优先级的交互机制。重点解释为何a.x最终指向新对象而输出undefined,以及b.x为何指向旧对象并打印[object Object],帮助开发者理解内存引用与属性查找的实际过程。

JavaScript引用类型赋值与属性访问的执行顺序详解

首先观察以下代码示例:


 <script>
 var a = {n:1}; 
 var b = a; 
 a.x = a = {n:2}; 
 console.log(a.x);// --> undefined 
 console.log(b.x);// --> [object Object] 
 </script>

这段代码看似简单,但运行结果却容易让人困惑,甚至产生误解。常见的疑问包括:“a.x已经指向了对象a,为什么log(a.x)的结果是undefined?”以及“b.x应该和a.x指向同一个对象,为什么日志中会显示出两个不同的对象?”

读者可以先尝试自行推导其中的原因和工作机理。如果能理清逻辑,便无需继续阅读后续分析。

接下来,我们将逐步拆解这段代码的执行过程,从而深入理解JavaScript中引用类型“赋值”操作的底层机制。

代码执行的第一步是:

var a = {n:1}; var b = a;

此时,变量a指向一个包含属性n且值为1的对象(暂称为对象A)。变量b被赋值为a,因此b也指向同一个对象A。也就是说,在这一阶段,a和b共同指向对象A:

JavaScript引用类型赋值与属性访问的执行顺序详解

这一步逻辑较为直观,我们继续分析下一行关键代码:

a.x = a = {n:2};

虽然JavaScript的赋值运算符遵循从右向左的结合顺序,但由于点运算符(.)具有最高的优先级,这行代码首先会计算a.x。

此时发生了一个关键变化——a所指向的对象(对象A)新增了一个属性x,尽管该属性的值目前为undefined:

JavaScript引用类型赋值与属性访问的执行顺序详解

从内存模型可以看出,由于b与a指向同一个对象A,要访问A的属性x,既可以使用a.x,也可以使用b.x。

随后,根据从右向左的赋值顺序,先执行a = {n:2}。此时,变量a的指向发生改变,转而指向一个新创建的对象{n:2}(暂称为对象B):

JavaScript引用类型赋值与属性访问的执行顺序详解

接着执行a.x = a。许多人会误以为这一步是“对象B新增属性x,并指向对象B自身”。

实际上并非如此。由于JavaScript引擎在第一步已经计算了a.x,此时解析器已确定a.x指的是对象A的属性x。因此,在同一条语句中后续进行赋值时,不会重新解析a.x为对象B的属性,而是继续向对象A的x属性赋值。

因此,a.x = a 的实际含义是:对象A的属性x指向了对象B:

JavaScript引用类型赋值与属性访问的执行顺序详解

此时结果已清晰可见。当执行console.log(a.x)时,变量a指向对象B,但对象B并没有属性x。JavaScript在查找属性时会上溯原型链,直到Object.prototype仍未找到指定属性,因此输出undefined。

当执行console.log(b.x)时,由于b仍指向对象A,b.x即访问对象A的属性x。该属性在之前的步骤中已被赋值为对象B,因此输出[object Object]。请注意,这里的[object Object]并非表示两个对象,而是对象隐式调用toString()方法后的字符串形式,即"[object Object]",它仅代表一个对象实例。

以上即为本文关于JavaScript引用类型赋值与属性访问机制的全部内容,希望读者能从中获益。

作者最新文章