对操作符优先级和数据存储方式考察题

对操作符优先级和数据存储方式考察题

var a = { n: 1 };
var b = a;
a.x = a = { n: 2 };
console.log(a.x);
console.log(b.x);
复制代码

这个题目考察了两个知识点

  • 不同数据类型在内存中的存储方式
  • 运算符优先级问题

知识点解析

1 不同数据类型在内存中的存储方式

基本类型和引用类型

JavaScript 数据类型目前是有 8 种,在大的方向可以分为两种,一种是基本类型,另外一种是引用类型。

  1. 基本类型
    基本类型也称为原始数据类型,基本数据类型有 7 种,number、string、boolean、null、undefined,symbol(ES6),bigint(ES10)
  2. 引用类型
    引用类型统称为 object 类型,细分的话有:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型 等。

变量的内存分配

变量内存分配.png

  1. 基本类型

    基本数据类型变量保存在栈(stack)中,它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将它们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。

  2. 引用类型

    javascript 的引用数据类型是同时保存在栈内存和堆内存中的对象。与其它语言的不同是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能操作对象在栈内存中的引用地址。准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。

运算符优先级

2 运算符优先级问题

优先级 运算符 说明 结合性
1 . [] () 字段访问、数组下标、函数调用以及表达式分组 从左往右
2 ++ -- - ~ ! delete new typeof void 一元运算符、返回数据类型、对象创建、未定义值 从右向左
3 * / % 乘法、除法、取余 从左向右
4 + - + 加法、减法、字符串连接 从左向右
5 << >> >>> 左位移、右位移、无符号右移 从左向右
6 < <= > >= instanceof 小于、小于或等于、大于、大于或等于、是否为特定类的实例 从左向右
7 == != === !== 等于、不等于、全等、不全等 从左向右
8 & 按位’与’ 从左向右
9 ^ 按位’异或’ 从左向右
10 ` ` 按位’或’
11 && 逻辑(短路)与 从左向右
12 ` ` 逻辑(短路)或
13 ?: 条件(三元)运算符 从右向左
14 = += -= *= /= %= &= 等 混合赋值运算符 从右向左
15 , 多个计算 按优先级计算,然后从右向左

题目分析

var a = { n: 1 };

由变量的内存分配我们得知:变量 a 存储在栈中具体值指向存在堆中的对象 { n: 1 }

var b = a;

此时变量 b 也指向对象 { n: 1 }

内存存储1.png

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

  1. . (点)的优先级比 = (等于) 高 所以限制性 a.x,对堆中的对象进行属性赋值,因为 x 声明未定义,所以是 undefined ,存在堆中的对象变成 { n: 1, x: undefined }

内存存储2.png

  1. 然后从右向左赋值,执行 a = { n: 2 }a 的指向变成新对象 { n: 2 }

内存存储3.png

  1. 最后一步执行赋值 a.x = a, 即时 a.x = { n: 2 }此时左侧a不会重新解析,而是使用最初解析a.x的时候的a,也就是旧对象。 旧对象变成{ n: 1, x: { n: 2 } }

内存存储4.png

总结

a = { n: 2 }
b = { n: 1, x: { n: 2 } }

console.log(a.x);

// undefined

console.log(b.x);

// { n: 2 }

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享