前言
上一章我们介绍了有关传统面向类的设计模式,实例化,多态,继承,我们了解到这些并没在js中得到应用,js有自己的方式来实现上面的内容,这一章我们将细致地展开js是怎么实现自己的混合对象“类“的
正文
在继承或者实例化时,JavaScript 的对象机制并不会自动执行复制行为。简单来说,JavaScript 中只有对象,并不存在可以被实例化的“类”。一个对象并不会被复制到其他对象,它们会被关联起来。由于在其他语言中类表现出来的都是复制行为,因此 JavaScript 开发者也想出了一个方法来。模拟类的复制行为,这个方法就是混入。接下来我们会看到两种类型的混入:显式和隐式。
显式混入
首先我们来回顾一下之前提到的 Vehicle 和 Car。由于 JavaScript 不会自动实现 Vehicle到 Car 的复制行为,所以我们需要手动实现复制功能。
Vehicle.drive.call( this )。这就是我所说的显式多态。在之前的伪代码中对应的语句是inherited:drive(),我们称之为相对多态。JavaScript并没有相对多态的机制。所以,由于 Car 和Vehicle 中都有 drive() 函数,为了指明调用对象,我们必须使用绝对(而不是相对)引用。我们通过名称显式指定 Vehicle 对象并调用它的 drive() 函数。但是如果直接执行 Vehicle.drive(),函数调用中的 this 会被绑定到 Vehicle 对象而不是Car 对象,这并不是我们想要的。因此,我们会使用 .call(this)来确保 drive() 在 Car 对象的上下文中执行。
隐式混入
通过在构造函数调用或者方法调用中使用 Something.cool.call( this ),我们实际上“借用”了函数 Something.cool() 并在 Another 的上下文中调用了它。最终的结果是 Something.cool() 中的赋值操作都会应用在 Another 对象上而不是Something 对象上。
小结
类是一种设计模式。许多语言提供了对于面向类软件设计的原生语法。JavaScript 也有类似的语法,但是和其他语言中的类完全不同。类意味着复制。传统的类被实例化时,它的行为会被复制到实例中。类被继承时,行为也会被复制到子类中。JavaScript 并不会(像类那样)自动创建对象的副本。在JavaScript 中模拟类是得不偿失的,虽然能解决当前的问题,但是可能会埋下更多的隐患。