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? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: