对象的扩展

2017-05-24  本文已影响0人  狒狒神

<pre>简而言之,对象的扩展就是通过类似于<strong>extend</strong>的方法,将对象的功能进行方便的管理(删除或者添加或者是修改)。
</pre>
我们能够轻松想到的方法是

  let extend = (destination, source) => {
    let i;
    for (i in source) {
      destination[i] = source
    }
  }

首先,在IE中<code>valueOf toString</code>等方法使用<code>for in</code>循环无法被遍历出来,那么在司徒正美的<code>mass Framework</code>中的<code>mix</code>方法是如何实现的呢?

  function mix(receiver, supplier) {
        var args = [].slice.call(arguments),
                i = 1,
                key, //如果最后参数是布尔,判定是否覆写同名属性
                ride = typeof args[args.length - 1] === "boolean" ? args.pop() : true;
        if (args.length === 1) { //处理$.mix(hash)的情形
            receiver = !this.window ? this : {};
            i = 0;
        }
        while ((supplier = args[i++])) { //允许合并多个对象
            for (key in supplier) { //允许对象糅杂,用户保证都是对象
                if (hasOwn.call(supplier, key) && (ride || !(key in receiver))) {
                    receiver[key] = supplier[key];
                }
            }
        }
        return receiver;
    }
  }

其实呢,这种类似于对象合并的方法,在es6中已经有了相应的原生方法即Object.assign(target, source1, source2),并且在各大浏览器已经得到广泛的支持。

但是,不得不注意的是这个方法只是对象的浅拷贝,即获取的是源对象的引用,而且如果存在同名属性,后面的属性会覆盖前面的属性(这一点在司徒的mix方法中已经做过考虑),那么我们需要一个方法来进行深拷贝的对象合并。

于是我做了如下的尝试:

function assign (target, source, boolean) {
    let args = [].slice.call(arguments),
        i = 1,
        key, //如果最后参数是布尔,判定是否覆写同名属性
        ride = typeof args[args.length - 1] === "boolean" ? args.pop() : true;
    let getSameObj = obj => {
        if (typeof obj !== "object") {
            return obj;
        }
        let s = {};
        if (obj.constructor != Array) {
            s = {};
            Object.getOwnPropertyNames(obj).forEach(item => {
                s[item] = getSameObj(obj[item])
            }) //遍历包括不可枚举的属性
        }
        return s;
    }
    if (args.length <= 1) {
        return target || {}
    }
    while ((source = getSameObj(args[i++]))) { //允许合并多个对象,并使用的是深拷贝
        Object.getOwnPropertyNames(source).forEach(key => {
            if (source.hasOwnProperty(key) && (ride || !(key in target))) {
                target[key] = source[key];
            }
        })
    }
    return target
}
上一篇下一篇

猜你喜欢

热点阅读