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

224 阅读2分钟

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

混入

在继承或者实例化的时候,JavaScript的对象机制并不会自动执行复制的行为。简单来说,JavaScript中只有对象,并不存在可以被实例化的“类”。一个对象并不会被复制到其他对象,它们会被关联起来。由于在其他语言中类表现出来的都是复制行为,因此JavaScript开发者也想出了一个方法来模拟类的复制行为,这个方法就是混入。混入的类型又有两种:显式和隐式。

显式混入

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

    // 非常简单的mixin()例子
function mixin(sourceObj,targetObj){
    for (var key in sourceObj){
        //只会在不存在的情况下复制
        if(!(key in targetObj)){
            targetObj[key] = sourceObj[key];
        }
    }
    return targetObj;
}
var Vehicle = {
    engines:1,
    ignition: function(){
        console.log("Turn on my engine");
    },
    drive:function(){
        this.ignition();
        console.log("Steering and moving forward!");
    }
};
var Car = mixin(Vehicle,{
    wheels:4,
    drive:function(){
        Vehicle.drive.call(this);
        console.log("Rolling on all" + this.wheels +"wheels!");
    }
});

现在Car中就有一份Vehicle属性和函数的副本了。从技术角度来说,函数实际上没有被复制,复制的只是函数引用。所以,Car中的属性ignition只是从Vehicle中复制过来的对于ignition()函数的引用。相反,属性engines就是直接从Vehicle中复制了值1。Car已经有了drive属性,所以这个属性没有呗mixin重写,从而保留了Car中定义的同名属性,实现了“子类”对“父类”属性的重写。

多态

来看下这条语句:Vehicle.drive.call(this)。这就是显式多态。JavaScript在ES6之前没有相对多态的机制,所以,由于Car和Vehicle中都有drive()函数,为了指明调用对象,我们必须使用绝对引用。我们通过名称显示指定Vehicle对象并调用它的drive()函数。

但是如果直接执行Vehicle.dirve(),函数调用中的this会被绑定到Vehicle对象而不是Car对象。这不符合预期效果,因此我们用了call确保drive()在Car对象的上下文中执行。