- 把下面obj对象克隆到一个新的对象obj1中
let obj = {
name: '车车',
age: 18,
skill: ['js', 'vue'],
family: {
sister: 'cgz',
parent: {
mather: 'wyp',
father: 'cyx'
}
},
say: function () {
console.log('hello!!')
},
b:undefined,
}
1.直接赋值
let obj1 = obj
obj1.family.sister = 'kkk' // obj也变了
console.log(obj) // 原来的对象obj.family.sister = 'kkk'
2.展开运算符
let obj1 = {...obj}
3.Object.assign
let obj1 = {}
console.log(Object.assign(obj1,obj))
obj1.skill[0] = 'css' //依旧改变了原来的对象obj
console.log(obj) //obj.skill[0] = 'css'
以上三种方法:直接赋值、展开运算符、Object.assign实现的克隆是浅度克隆;即:只能拷贝原始类型,对于引用值,拷贝的是地址,对象的引用,而不是对象本身,一旦内容改变,指向这个内容的地址中的内容都会变。
- 深度克隆:
1 . JSON.parse(JSON.stringify())
用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象。
let obj1 = JSON.parse(JSON.stringify(obj))
obj1.skill[1] = 'webpack' //obj不会被改变
console.log(obj1)
// 但是无法克隆函数和 undefined
- 自己实现一个深度克隆方法:
- 分析:
- 它要达到的目的是,不管是克隆的原始值还是引用值,当改变时另一个不会发生变化;我们根据浅度克隆可以知道,克隆原始值是直接拷贝,一个的改变不会影响另一个,但是引用值它拷贝的是地址,所以当一个改变会影响另一个跟他一起改变
- 首先遍历对象,看它的属性是原始值还是引用值,如果是原始值,则直接拷贝,如果是引用值,则需要判断是对象还是数组,做出辨别后建立相应的[]/{},然后拷贝[]/{}时,又需要判断里面的值是原始值还是引用值,如果是引用值,如刚才的方法进行循环判断辨别
- 过程:
1. 遍历对象 obj for …in
2. 判断是不是原始值 typeof() --> object
3. 如果是引用值,判断是数组还是对象
(1) . instanceof a的原型链上有没有b的原型
(2) . toString 建议用
(3) . constructor
4. 建立相应的数组或对象
5. 递归
function deepClone(origin,target){
var target=target||{};
toStr=Object.prototype.toString, //用toString方法区分对象和数组
arrStr="[object Arrary]"; //[]
for(var prop in origin){
if(origin.hasOwnProperty(prop)){
//只克隆自己的 排除原型链上的属性
if(origin[prop] !=="null" && typeof(origin[prop])=='object'){
//引用值
// if(toStr.call(origin[prop])==arrStr){
//数组
// target[prop]=[];
// }else{
//对象
// target[prop]={};
// }
target[prop]=toStr.call(origin[prop])==arrStr ? [] : {};
deepClone(origin[prop],target[prop]);
//属性里边的属性值是原始值还是引用值?进行相同的判断 调用自身实现相同功能 递归
}else{
//原始值
target[prop]=origin[prop]; //直接拷贝
}
}
}
return target;
}
deepClone(obj,obj1);
补充:数据类型判断 :
- typeof :如下,可以发现对于引用值和null,无法判断出真正的类型
typeof "a" //"string"
typeof 1 //"number"
typeof false //"boolean"
typeof undefined //"undefined"
typeof null //"object"
typeof [] //"object"
typeof {} //"object"
typeof function(){} //"function"
- A instanceof B : 判断A对象是不是B 构造函数构造出来的 返回true / false
function Person() {}
var person= new Person();
person instanceof Person //true
//注意看下面例子
person instanceof Object //true
[] instanceof Object //true
[] instanceof Array //true
function Person() {}
var person= new Person();
var obj={};
obj instanceof Person //false
person instanceof Array //false
所以:理解instanceof时应该这样理解:
A instanceof B : 看A对象的原型链上 有没有 B 的原型
- constructor :返回构造自己的构造函数
[].constructor //ƒ Array() { [native code] }
let obj = {}
obj.constructor //ƒ Object() { [native code] }
- Object.prototype.toString.call() :tostring方法会返回调用他的构造函数 ‘[object 构造函数]’
let toString = Object.prototype.toString;
toString.call(new String); // [object String]
toString.call(new Number) // [object Number]
toString.call(true) // [object Boolean]
toString.call(null); // [object Null]
toString.call(undefined); // [object Undefined]
toString.call(Symbol()) // [object Symbol]
toString.call([]); // [Object Array]
toString.call({}) // [object Object]
toString.call(function(){}) // [object Function]
toString.call(new Date); // [object Date]
toString.call(new RegExp) // [object RegExp]