一、栈和堆
1、栈
基础数据类型:undefined、null、number、boolean、string、symbol 皆存放在栈中(闭包除外)
特点:大小固定,按值访问,可被用户直接操作
let a = 1;let b = a;a = 100;console.log(b); // 1, b 不受 a 的影响
2、堆
引用数据类型:object、array、date、function 皆存放在堆中
特点:大小随机,按引用访问,不可被直接操作,用户表面上看似可以直接操作,但实际操作的是对其的引用
let obj = {num1: 117} // obj 存放在栈中,且是个地址; {num1 : 117} 存放在堆中,是个对象
注意以下区分:
let obj = {num: 1}let res = obj;obj.num = 0;console.log(res.num); // 0, obj 的指向和 res 为同一个堆中的数据, 一方更改另一方也会改
let obj = {num: 1}let res = obj;obj = {num: 0};console.log(res.num); // 1, obj 被指向了一个新的对象, 因此对其的修改不会影响到 res
二、连等赋值
1、基础:从左到右声明变量,走右到左赋值
下面的代码:
let a = b = 100;
实际上等同于:
let a;b; // 相当于 var bb = 100;a = b;
2、进阶:局部变量中使用连等,会被提升至全局变量
var a;var b;(function() {let a = b =1})();console.log(a); // undefined
实际相当于如下代码
(function() {let a = 1;b = 1; // b 被提升至全局变量})();
三、两者结合的应用
let obj = {num1: 117}let res = obj;obj.child = obj = { num2: 935 };var x = y = res.child.num2;console.log(obj.child); // undefinedconsole.log(res.num1); // 117console.log(y); // 935
1、obj.child = obj = {num2: 935}
- 1)、从左到右声明变量: ```javascript // 1、声明 obj.child, 原 obj 对象变为如下 let obj = { num1: 117, child: undefined }
// 2、声明 obj
- 2)、 从右到左赋值```javascript// 1. 为 obj 赋值let obj = {num2: 935}// 2. 为 obj.child 赋值, 注意这里的 obj 指的是原 obj 的地址, 而不是上一行刚被赋值的新的 objlet obj = {num1: 117,child: {num2: 935}}// 由于原 obj 的地址实际上是被 res 引用了,因此上面的代码可以理解为以下形式let res = {num1: 117,child: obj}
2、var y = res.child.num2
前面可以看出,res 其实就是 原 obj,且被赋予了新的属性 num2,因此可以正常输出
