object.assign()方法的作用:它是用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,基本语法:
- Object.assign(target,...source);
- const assign = require('object-assign');//经常会这样使用
如果target中的属性具有和source的属性相同的键,那么会被source覆盖掉,assign()方法的原理是使用源对象的[[get]]和目标对象的[[set]],会调取相关的getter和setter,String类型和Symbol类型的属性都会被拷贝.假如出现属性不可写的情况,会引发类型错误(TypeError),如果在引发错误之前添加属性,那么可以更改target对象.值得注意的一点,Object.assign会跳过值为null或undefined的源对象.
简易的复制对象操作如下:
let copy = Object.assign({},{a:0});
合并对象也会经常使用到,这里就会存在如果属性值相同的话,源就会覆盖目标的属性,一层层的覆盖:
let i = {a:0,b:1,c:2};
let j = {b:2,c:3};
let copy = Object.assign(i,j);
console.log(copy);// {a:0,b:2,c:3}
assign适合浅拷贝的处理方式因为它仅作为拷贝属性值处理,所以深拷贝它做不到,需要使用另一种方式处理:
function deal() {// 浅拷贝
let o1 = {a:0,b:{c:0}};
let o2 = Object.assign({},o1);
}
function deall() {// 深拷贝
let o1 = {a:0,b:{c:0}};
let o2 = JSON.parse(JSON.stringify(o1));
}
前面提到的仅可枚举的属性是可以拷贝的,那么可枚举属性是有判断的依据的,其中js中基本类型的原型属性是不可枚举的,如Object,Array,Number等,这些类型就不可以用for...in...便历,还有一种判断的方式,使用Object.propertylsEnumerable()方法可以判断此对象是否包含某个属性,并且这个属性是否可枚举.同时需要注意一点:如果判断的属性存在于Object对象的原型内,不管它是否可枚举都会返回false.
举个栗子:
function Person() {
this.name = "person";
}
Person.prototype = {
constructor: Person,
job: "student",
};
let pers = new Person();
Object.defineProperty(pers, "sex", {
value: "man",
enumerable: false //决定性属性,由此布尔值判断是否可枚举
});
上面栗子中pers用for...in...调用后,sex属性是没有输出的,也可用Object.proppertylsEnumerable()去判断.
Object.assign方法可以将原始类型包装为对象,这个在某些情况下需要注意使用.
let i='ab',j=0,k=true;
let obj = Object.assign({},i,null,j,undefined,k);
console.log(obj);// {"0":"a","1":"b"}
在拷贝过程中,如果发生了异常就会打断拷贝:
var target = Object.defineProperty({}, "foo", { value: 1, writable: false // target的foo属性只读。
}); Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only...注意这个异常是在拷贝第二个源对象的第二个属性foo时发生的。 console.log(target.bar); // 2,说明第一个源对象拷贝成功了。 console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。 console.log(target.foo); // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。 console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。 console.log(target.baz); // undefined,第三个源对象更是不会被拷贝到的。