Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

对象的扩展 #7

Open
SoloJiang opened this issue Jun 18, 2019 · 0 comments
Open

对象的扩展 #7

SoloJiang opened this issue Jun 18, 2019 · 0 comments
Labels

Comments

@SoloJiang
Copy link
Owner

SoloJiang commented Jun 18, 2019

简而言之,对象的扩展就是通过类似于extend的方法,
将对象的功能进行方便的管理(删除或者添加或者是修改)。

我们能够轻松想到的方法是

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

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

  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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant