vue 框架中,处理代码前,通常会生成上下文对象,利用对象之间的传递赋值特性,可以更方便的书写代码
而此笔记来正自于笔者在手写 vue 源码时,忘记了 JS 中的数据类型,导致很多地方不理解
JS 中的数据类型分为基本数据类型和引用数据类型,变量赋值也分为深拷贝和浅拷贝
基本数据类型又叫做基本数据类型或者值类型,引用数据类型又叫做复杂类型
堆栈
堆栈分配的区别:
- 栈:存储值类型,由操作系统自动分配释放存放函数的参数值、局部变量等,操作方式类似于数据结构中的栈
- 堆:存储引用类型,一般由程序员分配释放,如果程序员不释放,由垃圾回收机制回收
示例:
let num = 10
let obj = { age: 18 }
let obj2 = obj
值类型
所谓的简单数据类型/值类型指的是:在存储时,变量中存储的是值本身,JS 中的值类型有以下:
stringnumberbooleanundefinednull
题目:
let num1 = 10
let num2 = num1
num2 = 20
console.log(num1) // 10
num1声明赋值后在栈区开辟了一个空间,将let num2 = num1的意思是将num1的值赋值给num2,即num2的声明赋值重新在栈区开辟了空间
引用数据类型
所谓的复杂数据类型/引用类型指的是:在存储时,变量中存储的仅仅是地址(引用) ,因此叫做引用数据类型,在 JS 中,任意一个可以 用 new 关键字创建的对象都是引用数据类型,例如;
ObejctArrayDate- ...
let obj1 = {
age: 18
}
let obj2 = obj1
obj2.age = 20
console.log(obj1.age) // 20
引用数据类型在栈区存储的是其在堆区的地址,也就是说
let obj2 = obj1是将obj1的地址分配给了obj2,obj1最初的值{ age: 18 }是存储到堆区的。
同理,将引用数据类型作为函数参数传递,当函数内部对其操作时,也会改变原先的引用类型数值:
let a = [0, 1, 2, 3]
function addItem(arr) {
arr[4] = 4
}
addItem(a)
console.log(a) // [0, 1, 2, 3, 4]
注意点
浏览器环境和 node 环境
浏览器控制台执行顺序和 nodejs 环境下不一样,例如以下代码在浏览器和 node 中打印结果不同
let a = [0, 1, 2, 3]
// 先打印
console.log(a)
// 再调用函数
addItem(a)
function addItem(arr) {
arr[4] = 4
}
在浏览器中,打印的工作是靠后执行的,也就是说先执行了 addItem 函数,再打印,所以浏览器结果是:
而 node 则是按正常顺序:
引用类型赋值
前面讲过两个引用类型赋值其实是地址的传递,不会开辟新的内存,但如果我们赋一个新值,还是会额外开辟内存的:
let obj1 = { name: 'xj', age: 18 }
console.log(obj1.age) // 18
let obj2 = obj1
obj2.age = 19
console.log(obj1.age) // 19
// 赋一个新值,此时不会修改 obj1
obj2 = { name: 'xjj', age: 20 }
console.log(obj1.age) // 19
另外,数组中的某些方法和赋值的结果也不相同,例如:
let obj = { arr: [1111] }
let arr = obj.arr
// 1. 这个操作不会修改 obj
arr = [1111, 2222]
console.log(obj.arr) // [1111]
let arr2 = obj.arr
// 2. push 操作会修改 obj
arr2.push(2222)
console.log(obj.arr) // [1111, 2222]