JavaScript知识点回顾(二十七)——混入(二)

247 阅读2分钟

这是我参与8月更文挑战的第二十七天,活动详情查看:8月更文挑战

显式混入

由于JavaScript不会自动实现复制行为,所以我们需要手动实现复制功能。这个功能在许多的库和框架中被称为extend(),但是为了方便理解,我们称之为mixin()。

混合复制

回顾一下之前提到的mixin()函数:

        // 非常简单的mixin()例子
function mixin(sourceObj,targetObj){
    for (var key in sourceObj){
        //只会在不存在的情况下复制
        if(!(key in targetObj)){
            targetObj[key] = sourceObj[key];
        }
    }
    return targetObj;
}

它会遍历sourceObj的属性,如果再targeObj中没有这个属性就会进行复制。由于我们是目标对象初始化之后才进行复制,因此一定要小心不要覆盖目标对象的原有属性。

如果我们是先进行复制然后对目标对象进行特殊化的话,就可以跳过存在性检查:

        // 另一种混入函数,可能有重写风险
function mixin(sourceObj,targetObj){
    for (var key in sourceObj){
            targetObj[key] = sourceObj[key];
    }
    return targetObj;
}
var Vehicle={
    //...
};
//首先创建一个空对象并把Vehicle的内容复制进去
var Car = mixin(Vehicle,{});
//然后把新内容复制到Car中
mixin({
    wheels:4,
    drive:function(){
        //...
    }
},Car);

这两种方法都可以把不重叠的内容从Vehicle中显性复制到Car中。

由于两个对象引用的是同一个函数,因此这种复制(或者说混入)实际上并不能完全模拟面向类的语言中的复制。JavaScript中的函数无法用标准、可靠的方法进行真正的复制,所以只能复制对共享函数对象的引用。如果修改了共享的函数对象,那么双方都会受到影响。

显式混入是JavaScript一种不错的机制,不过并没有看起来那么的强大。虽然它可以把一个对象的属性复制到另一个对象中,但是带来的好处并没有很多,并且还存在刚刚说的函数对象引用的问题。

如果向目标对象中显式混入超过一个对象,就可以部分模仿多重继承行为,但是仍没有直接的方式处理函数和属性的同名问题。需要注意的是:只能在提高代码可读性的前提下使用显式混入,避免使用增加代码理解难度或者让对象关系更加复杂的模式。