目录
Object.is()
Object.assign()
ES5比较两个值是否相等,只有两个运算符:相等运算符(===)和严格运算符(===)。他们都有缺点,前者会自动转换数据类型,后者NaN不等于自身,以及 +0 等于-0,JavaScript缺乏一种运算,在所有环境中,只要两个值一样的,它们就应该相等。
ES6提出同值相等算法,用来解决这个问题。Object.is()就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)行为一致。
console.log(Object.is("a","a")); //true
console.log(Object.is({},{})); //false
但是,不同的是:+0 不等于-0,NaN等于自身。
console.log(+0 === -0); //true
console.log(NaN === NaN); //false
console.log(Object.is(+0,-0)); //false
console.log(Object.is(NaN,NaN)); //true
Object.is方法实现这个方法很简单。
Object.defineProperty(Object,"is"{
value : function(x,y){
if(x === y){
return x !== 0 || 1/x === 1/y;
}
return x !== x && y !== y;
},
configurable : true,
enumerable : false,
writable : true;
})
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到 目标对象(target)。Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。
const target = { a : 1};
const source1 = { b : 2};
const source2 = {c : 3};
console.log(Object.assign(target,source1,source2));
注意:如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
const target = { a : 1, b : 1};
const source1 = {b : 2 , c : 2};
const source2 = {c : 3};
Object.assign(target,source1,source2);
console.log(target); {a : 1, b :2,c :3,}
如果只有一个参数,Object.assign会直接返回改参数;如果该参数不是对象,则会先转为对象,然后返回;由于undefined和null无法转为对象,所以如果它们作为参数,就会报错。
const obj = { a : 1};
console.log(Object.assign(obj)); //{a : 1}
console.log(Object.assign(2)); Number {2}
console.log(Object.assign(undefined)); //error
console.log(Object.assign(null)); //error
如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同,首先,这些参数会都转为对象,如果无法转为对象,就会跳过,这意味着,如果undefined和null不在首参数,就不会报错。其他类型的值(即数值,字符串,和布尔值)不在首参数,也不会报错,但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。
let obj = { a : 1};
Object.assign(obj,2);
console.log(obj); {a : 1}
Object.assign(obj,undefined);
console.log(obj); { a: 1 }
Object.assign(obj,null);
console.log(obj); { a: 1 }
const v1 = "abc";
const v2 = true;
const v3 = 1;
let obj = Object.assign({},v1,v2,v3);
console.log(obj); {0 : a, 1 : b,2 : c}
Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性)也不拷贝不可枚举属性(enumerable:false),属性名为Symbol值的属性,也会被Object.assign拷贝
let obj = {age : 18,}
Object.defineProperty(obj,"name",{
value : "wang",
enumerable : false,
})
let person = {abc : "abc",}
Object.assign(person,obj);
console.log(person);
注意点
1.浅拷贝:Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性值是引用值的话,那么目标对象拷贝得到的是这个对象的引用。
const obj1 = { a : { b : "c",},}
const obj2 = { b : "a",}
Object.assign(obj2,obj1);
console.log(obj2);
obj1.a.b = "abc";
console.log(obj2); {a:{b:"abc"},b:"a"}
2.同名属性的替换:对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。
const target = { a : { b : { c : "d"}}};
const source = { a : { b : "c"}};
Object.assign(target,source);
console.log(target); //替换 {a : { b : "c"}}
3.数组的处理:Object.assign可以用来处理数组,视为对象。
let arr = Object.assign([1,2,3],[,5]);
console.log(arr);
4.取值函数的处理:Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
const source = {
get foo (){
return 1;
},
}
const target = {};
Object.assign(target,source);
console.log(target); {foo : 1}
常见用途
1.为对象添加属性
class Point {
constructor(x,y){
Object.assign(this,{x,y}); //相当于this.x = x;this.y = y;
}
}
const point = new Point(1,2);
console.log(point);
2.为对象添加方法
class SomeClass {
constructor(){
};
}
Object.assign(SomeClass.prototype,{
someMethod(arg1,arg2){
console.log(arg1,arg2);
},
anotherMethod(){
console.log(1);
}
})
console.log(SomeClass.prototype);
3.克隆对象---浅克隆
const clone = (origin) => Object.assign({},origin);
let obj = { a: { b: "c" } };
let cloneObj = console.log(clone(obj));
obj.a.b = "d";
console.log(cloneObj);
不过,采用这种方法克隆,只能克隆原始对象自身的对象,不能克隆它继承的值。如果想要保持继承链,采用下面的代码。
const clone = (origin) => {
let originProto = Object.getPrototypeOf(origin); //读__proto__属性
console.log(originProto);
return Object.assign(Object.create(originProto),origin);
}
4.合并多个对象
const merge = (...source) => Object.assign({},...source);
console.log(merge({a : 1},{b : 2},{c : 3}));
5.为属性提供默认值
const DEFAULTS = { //默认值对象
logLevel : 0,
outputFormat : "html",
};
const processContent = (options) =>{
options = Object.assign({},DEFAULTS,options);
console.log(options);
}
注意:由于存在浅拷贝问题,DEFAULTS对象和options对象的所有属性的值,最好都是简单类型,不要指向另一个对象。否则,DEFAULTS对象的该属性很可能不起作用。
主页传送门