原型链会有什么问题?
以我的拙见,这个问题的答案是:没有。 但是社区花了很多年的时间才将类的概念强加到不同的结构和库中,因此ECMA技术委员会决定无论如何都要添加它。
你会问,这有什么问题吗?这就是他们真正做的,在我们已经拥有的原型继承之上添加了一些构成,并决定将其称为类,这反过来又让开发人员认为他们正在处理一种面向对象的语言,而实际上它们并不是。
类只不过是语法糖
jS 没有完全的 OOP 支持,它从来没有,这是因为它从来都不需要它。
表面上,当前版本的类显示OOP范例,因为:
我们可以创建基本的类定义,用非常经典的语法将状态和行为分组在一起。
我们可以从一个类继承到另一个类。
我们可以在公有和私有之间定义属性和方法的可见性(尽管私有字段仍然是一个实验性的特性)。
我们可以为属性定义getter和setter。
我们可以实例化类。
那么为什么我说类是语法糖呢?因为尽管在表面上,它们看起来是非常面向对象的,但是如果我们试图做一些超出它们可能的事情,比如定义一个类扩展两个类(目前不可能的事情),我们需要使用下面的代码
// 辅助函数
function applyMixins(derivedCtor, baseCtors) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
let descriptor = Object.getOwnPropertyDescriptor(baseCtor.prototype, name)
Object.defineProperty(derivedCtor.prototype, name, descriptor);
});
});
}
class A {
methodA () {
console.log('A')
}
}
class B {
methodB () {
console.log('B')
}
}
class C {
}
// 使用 mixins
我们需要这样做,因为在JS中我们无法编写:
class A {
methodA(){
console.log("A")
}
}
class B {
methodB(){
console.log("B")
}
}
class C extends A, B {
}
在上面的示例中,关键部分应该是applyMixins函数。如果,你没有完全理解它试图做什么,但可以清楚地看到它正在访问所有类的原型属性来复制和重新分配方法和属性。这就是我们需要看到真相的地方:类只不过是在经过验证的原型继承模型之上的语法糖。
这是否意味着我们应该停止使用类? 当然不是,重要的是要理解它,而且如果我们想做些突破类的限制,那么我们就必须用原型来处理。
JS 的OOP 模型缺失了什么呢?
如果我们当前的OOP模型是如此之薄,仅是原型继承的抽象层,那么我们到底缺少什么呢? 是什么让JS真正成为OOP?
看这个问题的一个好方法就是看看TypeScript在做什么。该语言背后的团队通过创建一些可以翻译成JS的东西,无疑将 JS 推向了极限。这反过来也限制了它们的能力。
目前 JS 中缺失的一些OOP构造具有内在的类型检查功能,在动态类型语言中没有真正的意义,这可能是它们还没有被添加的原因。
接口
接口可帮助定义类应遵循的API。 接口的主要好处之一是,我们可以定义实现相同接口的任何类的变量,然后安全地调用其任何方法。
interface Animal {
speak()
}
class Dog implements Animal{
speak() {
console.log("Woof!")
}
}
class Cat implements Animal{
speak() {
console.log("Meau!")
}
}
class Human implements Animal{
speak() {
console.log("Hey dude, what's up?")
}
}
//如果我们在JS中有接口,我们可以放心地做:
let objects = [new Dog(), new Cat(), new Human()]
objects.forEach(o => o.speak())
当然,我们可以通过定义speak方法并覆盖它的类来实现同样的目的,但接口更加清晰和优雅。
抽象类
每当我尝试对我的代码进行完整的OOP操作时,我肯定会错过JS中的抽象类。 抽象类是定义和实现方法的类,但永远不会实例化。
这是一种可以扩展但从未直接使用的常见行为的分组方式。 这是一个很好的资源,并且绝对可以在当前JS领域内实现而不会花费太多精力。
静态多态
静态多态性使我们可以在相同的类中多次定义相同的方法,但是具有不同的签名。 换句话说,重复该名称,但要确保其接收不同的参数。
现在我们有了JS的rest参数,这使我们可以拥有一个任意数字,但是,这也意味着我们必须在方法中添加额外的代码来处理这种动态性。 相反,我们可以更清楚地区分方法签名,则可以将相同行为的不同含义直接封装到不同方法中。
如果你想开发小程序或者了解更多小程序的内容,可以通过第三方专业开发平台,来帮助你实现开发需求:厦门在乎科技-专注小程序开发、厦门app定制开发、网站开发