这是我参与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一种不错的机制,不过并没有看起来那么的强大。虽然它可以把一个对象的属性复制到另一个对象中,但是带来的好处并没有很多,并且还存在刚刚说的函数对象引用的问题。
如果向目标对象中显式混入超过一个对象,就可以部分模仿多重继承行为,但是仍没有直接的方式处理函数和属性的同名问题。需要注意的是:只能在提高代码可读性的前提下使用显式混入,避免使用增加代码理解难度或者让对象关系更加复杂的模式。