为什么会有浅拷贝和深拷贝
在js里,将对象赋值给一个新的变量:
var a = {a: 1, b: 2};
var b = a;
a===b; // true
因为a和b指向同一个内存地址,所以它们完全相同,而且改变其中一个,另一个也会改变。
在一些情境下,我们需要拷贝一个全新的对象,防止对原对象产生影响。
浅拷贝
常见的浅拷贝方法
$.extend({}, obj);
Array.prototype.slice();
Object.assign(); // let b = {...a}也一样
function shallowCopy(src) {
var dst = {};
for(var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
可以看出来,浅拷贝就是对象的第一层key-value的复制,对于value值为简单数据类型的可以做到与原对象互不影响。
如果是复杂的对象,浅拷贝还是不能解决之前提到的问题,这时候就需要深拷贝
深拷贝
常见的深拷贝方法
function deepClone(source){
// 先判断是否为对象
if(!source || typeof source !== 'object'){
throw new Error('请传入参数对象');
}
// 创建空的对象和数组
let targetObj = Array.isArray(source) ? [] : {};
// 如果value是简单数据类型,把对象的key-value拷贝到新的对象
// 如果value是对象, 递归调用方法,把对象最终解析到基本数据类型
for (let keys of Object.keys(source)) {
if(source[keys] && typeof source[keys] === 'object'){
targetObj[keys] = deepClone(source[keys]);
}else{
targetObj[keys] = source[keys];
}
}
return targetObj;
}
function deepClone(source){
return JSON.parse(JSON.stringify(source));
}
相对的,既然有深/浅拷贝,就会有深/浅比较
严格/浅比较 (strictEqual / shallowEqual)
严格比较
严格比较由JavaScript语言本身提供 ===
function strictEqual(a, b) {
return a === b
}
浅比较
这里我们引用react-redux里的源码
const hasOwn = Object.prototype.hasOwnProperty
// is方法可以判断基本数据类型是否相等
function is(x, y) {
if (x === y) {
return x !== 0 || y !== 0 || 1 / x === 1 / y // 排除 -0 === 0 返回 true的情况
} else {
return x !== x && y !== y // 排除NaN === NaN 返回 false的情况
}
}
// 浅比较(看上去一样)
export default function shallowEqual(objA, objB) {
// 首先对基本数据类型做比较
if (is(objA, objB)) return true
// 基本类型比较完成后,判断参数是否为对象,如果不是直接返回false,因为typeof null是object但null
的情况在is方法里可以判断,所以也直接返回false
if (
typeof objA !== 'object' ||
objA === null ||
typeof objB !== 'object' ||
objB === null
) {
return false
}
const keysA = Object.keys(objA)
const keysB = Object.keys(objB)
// 判断两个对象是否相同,可以先判断key的多少,不一样的肯定不同
if (keysA.length !== keysB.length) return false
// 递归判断每一层的key-value,此处与深拷贝类似
for (let i = 0; i < keysA.length; i++) {
if (!hasOwn.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
return false
}
}
return true
}
为什么会有浅拷贝和深拷贝
在js里,将对象赋值给一个新的变量:
因为a和b指向同一个内存地址,所以它们完全相同,而且改变其中一个,另一个也会改变。
在一些情境下,我们需要拷贝一个全新的对象,防止对原对象产生影响。
浅拷贝
常见的浅拷贝方法
可以看出来,浅拷贝就是对象的第一层key-value的复制,对于value值为简单数据类型的可以做到与原对象互不影响。
如果是复杂的对象,浅拷贝还是不能解决之前提到的问题,这时候就需要深拷贝
深拷贝
常见的深拷贝方法
相对的,既然有深/浅拷贝,就会有深/浅比较
严格/浅比较 (strictEqual / shallowEqual)
严格比较
严格比较由JavaScript语言本身提供 ===
浅比较
这里我们引用react-redux里的源码