美文网首页
对象的扩展

对象的扩展

作者: 狒狒神 | 来源:发表于2017-05-24 19:45 被阅读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
    }
    

    相关文章

      网友评论

          本文标题:对象的扩展

          本文链接:https://www.haomeiwen.com/subject/mztgxxtx.html