JavaScriptES6对象的Object.is和Object.assign方法详解

目录

 

Object.is()

Object.assign()


Object.is()

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()

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对象的该属性很可能不起作用。

主页传送门

你可能感兴趣的:(JavaScriptES6.0,JavaScriptES6.0)