JavaScript中的类有什么问题呢?

简介: 并不是说 JS 的类有问题,但是如果你使用该语言已有一段时间,特别是使用过ES5,那么你可能就知道了从原型继承到当前类模型的演变。

原型链会有什么问题?

以我的拙见,这个问题的答案是:没有。 但是社区花了很多年的时间才将类的概念强加到不同的结构和库中,因此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定制开发、网站开发

相关文章
|
3月前
|
JavaScript 前端开发
js开发:请解释原型继承和类继承的区别。
JavaScript中的原型继承和类继承用于共享对象属性和方法。原型继承通过原型链实现共享,节省内存,但不支持私有属性。
33 0
|
3月前
|
JavaScript
js开发:请解释什么是ES6的类(class),并说明它与传统构造函数的区别。
ES6的类提供了一种更简洁的面向对象编程方式,对比传统的构造函数,具有更好的可读性和可维护性。类使用`class`定义,`constructor`定义构造方法,`extends`实现继承,并可直接定义静态方法。示例展示了如何创建`Person`类、`Student`子类以及它们的方法调用。
38 2
|
3月前
|
JavaScript 前端开发
js开发:请解释原型继承和类继承的区别。
JavaScript中的原型继承和类继承用于共享对象属性和方法。原型继承利用原型链查找属性,节省内存但不支持私有成员。类继承通过ES6的class和extends实现,支持私有成员但占用更多内存。两者各有优势,适用于不同场景。
36 0
|
2月前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念,它允许我们基于现有的类(或构造函数)创建新的类
【6月更文挑战第15天】JavaScript继承促进代码复用与扩展,创建类层次结构,但过深的继承链导致复杂性增加,紧密耦合增加维护成本,单继承限制灵活性,方法覆盖可能隐藏父类功能,且可能影响性能。设计时需谨慎权衡并考虑使用组合等替代方案。
39 7
|
4天前
|
JavaScript 前端开发
记录Javascript数组类练习
记录Javascript数组类练习
|
2月前
|
JavaScript 前端开发
记录Javascript数组类练习
记录Javascript数组类练习
17 1
|
2月前
|
JavaScript 前端开发 Java
【JavaScript】ECMAS6(ES6)新特性概览(二):解构赋值、扩展与收集、class类全面解析
【JavaScript】ECMAS6(ES6)新特性概览(二):解构赋值、扩展与收集、class类全面解析
30 2
|
2月前
|
存储 JavaScript 前端开发
【JavaScript】JavaScript 中的 Class 类:全面解析
【JavaScript】JavaScript 中的 Class 类:全面解析
42 1
|
1月前
|
JavaScript 索引
js 类数组 转 数组
js 类数组 转 数组
28 0
|
1月前
|
JavaScript 前端开发
JavaScript编码之路【ES6新特性之Class类】(二)
JavaScript编码之路【ES6新特性之Class类】(二)
15 0

热门文章

最新文章