复制对象中的一部分属性给另一个对象

8,213 阅读3分钟

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

首先我们先预定义两个对象一个是被赋值对象targetObj,一个是赋值对象originObj,下面进行赋值时就使用这两个对象进行操作。

方法一(基本循环)

基本方法就是循环,以for循环为例:

for(let key in targetObj) {
    targetObj[key] = originObj[key]
}

这是最基本的用法,适用于任何语言的使用者,只要了解循环语法的人都会使用,所想就是所得,很好理解。

方法二(解构赋值)

剔除差异属性:假设targetObj有a、b、c、d四个属性,originObj有a、b、c三个属性

let {d, ...targetObj} = originObj

es6解构赋值(需要考虑环境是否支持es6语法,不过现在基本都支持,框架的工程化默认支持转成es5,所以基本不需要顾虑),这种方法适用于差异属性比较少,反之差异属性比较多的话,就列出需要赋值的属性使用同样的方法进行解构赋值,比较简洁明了。

方法四(自执行函数)

const targetObj = (({a, d, e}) => ({a, d, e}))(originObj)

此方法看起来很简洁大气,一行代码,不拖泥带水。其实,这种方法跟方法三解构赋值是一个原理,只是通过函数来承载了,入参是个对象,返回值也是个对象,这两个对象的属性是一致的。

方法五(自定义extend函数)

function extend(originObj) {
    var obj = {},
    keyAttr = Array.prototype.slice.call(arguments).slice(1);
    keyAttr.forEach(function(val, index) {
        if (val in obj) { 
            obj[val] = originObj[val] 
        }
    })
    return obj
}
targetObj = extend(originObj, 'key1', 'key2')

此方法主要使用了arguments对象进行函数参数的获取。在js中不需要明确指出参数名,就可以通过arguments获取函数的参数,有关arguments这里不作详细介绍,但是需要注意,例如:

var length = 10;
function fn() {
  console.log(this.length);
}

var obj = { 
  method: function(fn) {
    fn();
    arguments[0]();
  }
};

obj.method(fn, 1); 输出:10,2

这里有2个需要注意的点。fn函数里面的this的指向:

1.第一个值为10,执行的是method里面的第一行"fn() ",这里this指向的window。所以输出的值为最外层定义的length。

2.第二个值为2,执行的是method里面的第二行"arguments[0] ()"(arguments[0] () => fn() ),这里this执行的是arguments这个对象,所以输出值为arguments的长度

另外需要注意严格模式下:

1 在严格模式下arguments作为了一个保留字,那么如果在定义arguments相关的变量和函数,则会报语法错误。

2 arguments在严格模式下属于传入的实参对象,并且是不可变的,即不可在函数内部通过arguments来修改实参值。

3 禁止使用arguments.callee,caller,在函数内部不能通过这种方式获取自己的引用了

方法五(reduce函数)

const pickFn = (originObj, keyArr) =>
    keyArr.reduce((total, val) => (val in obj && (total[val] = obj[val]), total), {});
    
targetObj = pickFn(originObj, ['a', 'd', 'e'])

该方法主要运用的是reduce的叠加,主要还是循环的使用。

在业务开发中复制对象中的一部分属性给另一个对象的场景还是很多的,比较常见的一个场景就是列表的编辑,通常情况下对列表行数据进行编辑数据回显时,数据是直接从该行直接获取的,而该行的数据字段是多余编辑弹窗的数据字段的,这时候我们就需要用到这些方法中的某个进行部分属性的赋值。