javascript中Rest/Spread与Object.assign的不同

ES6中的Rest/Spread使用的很广泛了,
比如简单的(浅)复制一个数组:

const arr1 = [10, 20, 30];

// 复制一下
const copy = [...arr1];

console.log(copy);    //  [10, 20, 30]

再比如给一个函数传递参数,参数需要一个个地传递,现在参数都在一个数组里面:

const arr = [10, 20, 30]
// 和这行一样 console.log(Math.max(10, 20, 30));
console.log(Math.max(...arr));    // → 30

再比如合并数组:

const arr1 = [10, 20, 30];
const arr2 = [40, 50];
console.log([...arr1,...arr2]);  // [10, 20, 30, 40, 50]

不仅对数组,对对象也有类似的操作;
比如复制一个对象的自己的可枚举的属性(own enumerable properties),

const obj1 = {
  a: 10,
  b: 20
};

const obj2 = {
  ...obj1,
  a: 30
};

console.log(obj2);    // → {a: 30, b: 20}   

从上面也可以看出,后面属性值的会覆盖前面的属性。再比如合并对象:

const obj1 = {a: 10};
const obj2 = {b: 20};
const obj3 = {c: 30};

console.log({...obj1, ...obj2, ...obj3});    // → {a: 10, b: 20, c: 30}

不过上面的这个功能,用Object.assign也可以实现:

console.log(Object.assign({}, obj1, obj2, obj3));    // → {a: 10, b: 20, c: 30}

不过, spread 和 Object.assign 的效果并不总是一样的:

Object.defineProperty(Object.prototype, 'aa', {
    get(value) {
        console.log('prototype get aa called!');
        return 'prototype aa';
    },
    set(value) {
        console.log('prototype set aa called', value);
    }
});
Object.defineProperty(Object.prototype, 'bb', {
    get(){
        console.log('prototype get bb called!');
        return 'prototype bb';
    },
    set(value) {
        console.log('prototype set bb called!', value);
    }
});

let source = { };
let target = { };

Object.defineProperty(source, 'b', {
    set() {
        console.log('source set b');
    },
    get() {
        console.log('source get b');
        return 'souce of b';
    },
    enumerable: true
});

Object.defineProperty(source, 'c', {
    set() {
        console.log('source set c');
    },
    get() {
        console.log('source get c');
        return 'souce of c';
    },
    enumerable: true
});

Object.defineProperty(source, 'd', {
    set() {
        console.log('source set d');
    },
    get() {
        console.log('source get d');
        return 'souce of d';
    },
    enumerable: false
});


Object.defineProperty(target, 'a', {
    get(){
        console.log('target get a');
        return 'target of a'
    },
    set() {
        console.log('target set a');
    },
    enumerable: true
});

Object.defineProperty(target, 'c', {
    set(v) {
        console.log('target set c,', v);
    },
    get() {
        console.log('target get c');
        return 'target of c';
    },
    enumerable: true
});

console.log('Object.assign(target, source)结果:');
Object.assign(target, source);

console.log('{ ...target, ...source }结果:');
k={ ...target, ...source };

控制台输出:

Object.assign(target, source)结果:
source get b
source get c
target set c, souce of c
{ ...target, ...source }结果:
target get a
target get c
source get b
source get c

直接从MDN复制过来解释吧:

  1. Object.assign

Properties in the target object will be overwritten by properties in the sources if they have the same key. Later sources’ properties will similarly overwrite earlier ones.

The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties.

  1. spread

It copies own enumerable properties from a provided object onto a new object.

参考文献
https://css-tricks.com/new-es2018-features-every-javascript-developer-should-know/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值