H5游戏开发Web前端之路让前端飞

JavaScript中拷贝对象方法总结

2017-05-04  本文已影响113人  csRyan

对象拷贝是在js中最基本的对象操作。

浅拷贝

function sallowCopy(source) {
    // source 不是对象,而是【原始类型】的情况
    // 原始类型说明详见http://www.jianshu.com/p/b161aeecb6d6
    if (null == source || "object" != typeof source) return source;
    
    // 其他情况都将 source 当作简单对象来处理
    var target = {};
    for (var key in source) {
        if (source.hasOwnProperty(key)) {  // 仅拷贝自身的属性
            target[key] = source[key];
        }
    }
    return target;
}
/*
这个浅拷贝会将source对象上的所有[可枚举属性](http://www.jianshu.com/p/7b8da1db32b3)都拷贝到target对象上,不包括原型链上的属性。
*/

浅复制仅仅复制嵌套对象的地址

var outter = {
    outter_property:333,
    // inner 是嵌套对象
    inner: {
        inner_property:222
    }
};

var copy = sallowCopy(outter);
// copy.inner 与 outter.inner 是同一个对象,它们指向同一个内存地址。

copy.inner.inner_property = 'new value!';
console.log(outter.inner.inner_property);   // new value!
//改变了copy.inner对象,也就改变了outter.inner对象

拷贝需要注意的问题有很多:

这些问题,上面这个方法都没有考虑,它只适用于简单对象的复制,这个方法仅用于示范浅拷贝的原理。事实上很难写出也没必要写出一个能够应付所有情况的完美方法。只要根据实际情况选择,往往都能找到一个满足需要的方法。文末会列举现有的、常见的拷贝函数。

深拷贝

function deepClone(obj) {
    var copy;

    // Handle number, boolean, string, null and undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = deepClone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = deepClone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

深拷贝会复制嵌套的对象:

var outter = {
    outter_property:333,
    inner: {
        inner_property:222
    }
};

var copy = deepClone(outter);
// copy.inner 与 outter.inner是不同的两个对象,从此互不干涉
copy.inner.inner_property = 'new value!';
console.log(outter.inner.inner_property);   // 222
// 修改copy.inner.inner_property,outter.inner.inner_property不会改变

上面这个深拷贝方法除了可以处理原始类型和简单对象以外,还能处理Date和Array,依然不能处理Number对象、RegExp对象、Function对象等。不过已经比较实用了。

现成的拷贝方法

Object.assign({}, 'abcd')
// Object {0: "a", 1: "b", 2: "c", 3: "d"}

参考资料

上一篇 下一篇

猜你喜欢

热点阅读