We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
堆和栈的区别 其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。 堆和栈都是内存中划分出来用来存储的区域。 栈(stack)为自动分配的内存空间,它由系统自动释放; 而堆(heap)则是动态分配的内存,大小不定也不会自动释放。
堆和栈的区别
其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。 堆和栈都是内存中划分出来用来存储的区域。 栈(stack)为自动分配的内存空间,它由系统自动释放; 而堆(heap)则是动态分配的内存,大小不定也不会自动释放。
基本数据类型有五种:number、string、boolean、null、undefined。基本数据类型存放在栈中。 存放在栈中的数据具有数据大小确定,内存空间大小可以分配、直接按值存放的特点。 所以存放在栈中的数据可以直接访问。在JavaScript中,基本的数据类型值是不可更改的。
引用数据类型:是存放在堆内存中。引用数据类型的变量并不是存放的实际值, 而是一个存放在栈内存的指针,该指针指向堆内存中的某个地址。每个数据所占的空间大小不一致, 需要根据情况进行特定的分配。与基本数据类型不同,引用类型的值是可以改变的。
赋值是将某一数值或对象赋给某个变量的过程,分两种情况:
对基本数据类型的赋值,两个变量相互不影响: var a = 1; var b = a; a = 2; console.log(a); // 2 console.log(b); // 1 复制代码对引用数据类型进行赋址操作,两个变量指向同一个对象, 改变变量a的值会影响变量b的值,哪怕改变的只是对象a中的基础数据类型: var a = { name: 'Jane', book: { name: 'Vue.js', price: 50 } }; var b = a; b.name = 'hahaha'; b.book.price = 52; console.log(a); // { name: 'hahaha', book: { name: 'Vue.js', price: 52 } } console.log(b); // { name: 'hahaha', book: { name: 'Vue.js', price: 52 } } 复制代码通常开发中我们不希望出现这种相互影响的情况,所以需要浅拷贝或者深拷贝。
重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,只拷贝一层,不能对对象中的子对象进行 拷贝 如果属性是基本数据类型,拷贝的是基本数据类型的值;如果属性是引用类型,拷贝的是内存地址, 所以如果一个对象改变了这个地址,就会影响到另外一个对象。
简单说,浅拷贝只解决了第一层的问题,即第一层的基本数据类型和引用类型数据的引用地址
赋值示例: var a = {a:2,b:2} var b = a undefined b.a = 3 // a {a: 3, b: 2} // b {a: 3, b: 2} 浅拷贝示例: var ac = {a: 2, b:3, obj: {a1:2},arr: [1,2,3]} var c = cloneShallow(ac) // 浅拷贝函数 // c 等于 {a: 2, b: 3, obj: {a1:2}, arr: [1,2,3]} c.a = 1 // ac.a = 2 // 结论是 普通属性不会改变 c.obj.a1 = 3 // ac.obj.a1 = 3 // 结论是 引用属性指向同一个地址 会改变
浅拷贝几种方法:
var a = { name: 'Jane', book: { name: 'Vue.js', price: 50 } }; var b = Object.assign({}, a); b.name = 'hahaha'; b.book.price = 52; console.log(a); // { name: 'Jane', book: { name: 'Vue.js', price: 52 } } console.log(b); // { name: 'hahaha', book: { name: 'Vue.js', price: 52 } }
var b = {...a}; b.name = 'hahaha'; b.book.price = 52; console.log(a); // { name: 'Jane', book: { name: 'Vue.js', price: 52 } } console.log(b); // { name: 'hahaha', book: { name: 'Vue.js', price: 52 } }
slice()方法返回一个新的数组对象,这个对象是由begin和end(不包括end)决定的原数组的浅拷贝。原数组不会被改变。 var a = [0, '1', [2, 3]]; var b = a.slice(1); console.log(b); // ['1', [2, 3]] a[1] = '99'; a[2][0] = 4; console.log(a); // [0, '99', [4, 3]] console.log(b); // ['1', [4, 3]] 复制代码从上面的代码可以看出,a[1]改变之后b[0]并没有改变,a[2][0]改变之后相应的b[1][0]跟着改变了。 说明slice()是浅拷贝,相应的还有concat等。
function cloneShallow(source) { var target = {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } return target; }
深拷贝是对对象以及对象的所有子对象进行拷贝,浅拷贝的进阶版 深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。 当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相较于浅拷贝速度慢并且花销更大。 深拷贝的两个对象互不影响。
1.es6方法 function isObject(x) { return Object.prototype.toString.call(x) === '[object Object]'; } function cloneDeep4(source, hash = new WeakMap()) { if (!isObject(source)) return source; if (hash.has(source)) return hash.get(source); let target = Array.isArray(source) ? [...source] : { ...source }; // 改动 1 hash.set(source, target); Reflect.ownKeys(target).forEach(key => { // 改动 2 if (isObject(source[key])) { target[key] = cloneDeep4(source[key], hash); } else { target[key] = source[key]; } }); return target; }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
1.参考文章 2.参考文章-推荐 3.参考文章
拓展
数据类型
基本数据类型有五种:number、string、boolean、null、undefined。基本数据类型存放在栈中。
存放在栈中的数据具有数据大小确定,内存空间大小可以分配、直接按值存放的特点。
所以存放在栈中的数据可以直接访问。在JavaScript中,基本的数据类型值是不可更改的。
引用数据类型:是存放在堆内存中。引用数据类型的变量并不是存放的实际值,
而是一个存放在栈内存的指针,该指针指向堆内存中的某个地址。每个数据所占的空间大小不一致,
需要根据情况进行特定的分配。与基本数据类型不同,引用类型的值是可以改变的。
赋值
赋值是将某一数值或对象赋给某个变量的过程,分两种情况:
浅拷贝
重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,只拷贝一层,不能对对象中的子对象进行
拷贝
如果属性是基本数据类型,拷贝的是基本数据类型的值;如果属性是引用类型,拷贝的是内存地址,
所以如果一个对象改变了这个地址,就会影响到另外一个对象。
简单说,浅拷贝只解决了第一层的问题,即第一层的基本数据类型和引用类型数据的引用地址
Object.assign()把所有可枚举属性从一个或多个对象复制到目标对象,返回目标对象
深拷贝
深拷贝是对对象以及对象的所有子对象进行拷贝,浅拷贝的进阶版
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。
当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相较于浅拷贝速度慢并且花销更大。
深拷贝的两个对象互不影响。
缺点:这种方法虽然可以实现数组或对象深拷贝,但不能处理函数和正则,
因为这两者基于JSON.stringify和JSON.parse处理后,得到的正则就不再是正则(变为空对象),
得到的函数就不再是函数(变
为null)了。
手工实现
loadsh解决更多的复杂判断
The text was updated successfully, but these errors were encountered: