深度克隆(deepclone)
深度克隆方法,返回一个新的克隆对象
这里得说明深拷贝与钱拷贝的区别,浅拷贝是复制一个对象的引用,深拷贝是chone一个新的对象,与原对象有着不同的内存地址
1.1 原始值类型
String Number function Boolean undefined Symbol(es6引入)
1.2 引用值类型
Object Array Null
```
**1.3 判断基本类型**
```js
使用 typeOf 进行判断
// 原始值类型
console.log(typeof 'sfsf') // "string"
console.log(typeof 22) // "number"
console.log(typeof function(){}) // "function"
console.log(typeof true) // "boolean"
console.log(typeof undefined) // "undefined"
console.log(typeof Symbol('2')) // "symbol"
// 引用值类型
console.log(typeof {}) //"object"
console.log(typeof []) // "object"
console.log(typeof null) // "object"
2.1 constructor
[].constructor == Array
[].constructor == Array / Object
弊端此方法容易被改写
let arr = [];
arr.constructor = Object
console.log(arr.constructor == Array) // false
console.log(arr.constructor == Object) // true
2.2 instanceof
运算符可以用来判断某个构造函数的prototype属性所指向的對象是否存在于另外一个要检测对象的原型链上。
console.log([] instanceof Array) // true
console.log([] instanceof Object) // true
console.log({} instanceof Array) // false
console.log({} instanceof Object) // true
判断一个Object是不是数组(这里不是口误,在JavaScript当中,数组实际上也是一种对象),如果这个Object的原型链上能够找到Array构造函数的话, 那么这个Object就也是一个数组,如果这个Object的原型链上只能找到Object构造函数的话,那么它就不是一个数组。
2.3 Object.prototype.toString.call() 建议
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call({}) //"[object Object]"
Object.prototype.toString.call(null) //"[object Null]"
注意,这里的call改变this的指向是必不可少的,如果缺少
Object.prototype.toString([]) //"[object Object]"
Object.prototype.toString({}) //"[object Object]"
Object.prototype.toString(null) //"[object Object]"
通过递归遍历一个对象,返回一个新的对象
/**
* 深拷贝
* @param {*} target 要深拷贝的值
*/
function deepclone(target) {
if (typeof target !== "object") return target;
let obj;
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
};
}
if (Array.isArray(target)) {
obj = [];
} else {
obj = {};
}
for (let prop in target) {
// obj.hasOwnProperty 判断某个对象是否含有指定的属性
// 该方法会忽略掉从原型链上继承的属性
if (target.hasOwnProperty(prop)) {
if (typeof target === "object") {
obj[prop] = deepclone(target[prop]);
} else {
obj[prop] = target[prop];
}
}
}
return obj;
}
console.log(deepclone({ a: 1, b: { c: 2 } })); // 打印 { a: 1, b: { c: 2 } }
console.log([1, 23, { a: 2 }]); // 打印 [1, 23, { a: 2 }]
console.log(deepclone(5)); // 打印 5
通过hack方式实现
function deepclone(target) {
return JSON.parse(JSON.stringify(target));
}
console.log(deepclone({ a: 1, b: { c: 2 } })); // 打印 { a: 1, b: { c: 2 } }
console.log([1, 23, { a: 2 }]); // 打印 [1, 23, { a: 2 }]
console.log(deepclone(5)); // 打印 5
通过Object.getPrototypeOf() 获取目标对象的原型,通过Object.assign()生成一个新的对象
function deepclone(target) {
if (typeof target !== "object") return target;
return Object.assign(
{},
Object.create(Object.getPrototypeOf(target)),
target
);
}
console.log(deepclone({ a: 1, b: { c: 2 } })); // 打印 { a: 1, b: { c: 2 } }
console.log([1, 23, { a: 2 }]); // 打印 [1, 23, { a: 2 }]
console.log(deepclone(5)); // 打印 5
通过Object.getPrototypeOf() 获取目标对象的原型,通过扩展运算符以及proto来实现深度克隆(仅适用于浏览器端)
function deepclone(target) {
if (typeof target !== "object") return target;
return {
__photo__: Object.getPrototypeOf(target),
...target
};
}
console.log(deepclone({ a: 1, b: { c: 2 } }));
console.log([1, 23, { a: 2 }]);
console.log(deepclone(5));