js 的数据类型
基本类型:字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。 引用数据类型:对象(Object)、数组(Array)、函数(Function)。
基本类型和引用类型的区别:
基本类型在赋值时,赋值的是变量的副本;修改 b 并不会改变 a 的值
let a = '123'
let b = a
b = '456'
console.log(a) // '123'
console.log(b) // '456'
引用类型在赋值时,赋值的是变量的指针,两个指针指向同一个内存地址,修改 b 的值会改变 a 的值,因为他们是同一个对象
let a = {}
a.str = '123'
let b = a
b.str = '456'
console.log(a.str) // '456'
console.log(b.str) // '456'
变量是怎样存储的?
字符串:存在堆里,栈中为引用地址,如果存在相同字符串,则引用地址相同。
数字:小整数存在栈中,其他类型存在堆中。
其他类型:引擎初始化时分配唯一地址,栈中的变量存的是唯一的引用。
空字符串,布尔,null,undefined 等基础数据类型存在栈中(v8 odd ball)
https://blog.csdn.net/qianyu6200430/article/details/120426595
浅拷贝,深拷贝
深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
浅拷贝
浅拷贝只对对象的各个属性进行一层的拷贝,如拷贝属性是引用对象,则仍然指向同一个地址
javascript
function shallowCopy (obj) {
let newObj = {}
for(let prop in obj) {
if(obj.hasOwnProperty(prop)) {
newObj[prop] = obj[prop]
}
}
return newObj
}
let a = {
str: '123',
obj: {
str: '123'
}
}
b = shallowCopy(a)
b.str = '456'
b.obj.str = '456'
console.log(a.str) // '123'
console.log(a.obj.str) // '456' a.obj 和 b.obj 指向同一个地址
深拷贝
深拷贝递归地把对象各个属性中的对象进行拷贝,返回一个对象的复制
方法1: JSON 简单粗暴
javascript
b = JSON.parse(JSON.stringify(a))
缺点是无法拷贝函数,原型链上的属性和方法
方法2: 用递归的简单实现
javascript
function isObject (obj) {
return typeof obj === 'object' && obj !== null
}
function deepClone (obj) {
if(!isObject(obj)) return obj
let target = Array.isArray(obj) ? [] : {}
for(let k in obj) {
if(obj.hasOwnProperty(k)) {
if(isObject(obj[k])) {
target[k] = deepClone(obj[k])
} else {
target[k] = obj[k]
}
}
}
return target
}
方法3: 用堆栈的简单实现
javascript
// 判断 object
function isObject(value) {
var type = typeof value;
return value != null && (type == 'object' || type == 'function');
}
function deepClone(obj) {
const root = {} // 根元素
// 堆栈
const loopList = [
{
parent: root,
key: undefined,
data: obj
}
]
while(loopList.length) {
const node = loopList.pop()
const { parent, key, data } = node
let res = parent
if (typeof key !== 'undefined') {
res = parent[key] = {}
}
for(let k in data) {
if(data.hasOwnProperty(k)) {
if(isObject(res)) { // 把对象压入栈中
loopList.push({
parent: res,
key: k,
data: data[k]
})
} else {
res[k] = data[k] // 基本数据类型直接赋值
}
}
}
}
}