当前位置: 首页 > Web前端 > JavaScript

JavaScript中的类有什么问题?_0

时间:2023-03-27 01:54:42 JavaScript

作者:FernandoDoglio译者:前端小智来源:meidum再次点赞,微信搜索【大千世界】,B站关注【前端小智】这个没有大厂背景,但是有一个积极的态度的人。本文已收录到GitHubhttps://github.com/qq44924588...,文章已分类,也整理了很多我的文档和教程资料。并不是说JS中的类有什么问题,但如果你已经使用该语言一段时间,尤其是ES5,那么你可能会意识到从原型继承到当前类模型的演变。原型链有什么问题?在我看来,这个问题的答案是:不。但社区花了数年时间才将类的概念强加到不同的结构和库中,因此ECMA技术委员会决定无论如何都要添加它。你问这有什么问题?这就是他们真正所做的,在我们已有的原型继承之上进行一些组合,并决定将其称为类,这反过来又让开发人员认为他们正在处理一种面向对象的语言,而实际上他们不是。类只不过是语法糖jS没有完整的OOP支持,它从来没有,那是因为它从来不需要它。从表面上看,当前版本的类显示了一种OOP范式,因为:我们可以创建基本的类定义,以非常经典的语法将状态和行为组合在一起。我们可以从一个类继承到另一个类。我们可以定义属性和方法在公有和私有之间的可见性(尽管私有字段仍然是一个实验特性)。我们可以为属性定义getter和setter。我们可以实例化类。那么为什么我说类是语法糖呢?因为虽然从表面上看,它们看起来非常面向对象,但是如果我们试图做一些超出它们可能的事情,比如定义一个扩展两个类的类(目前不可能的事情),我们需要使用下面的代码//辅助函数functionapplyMixins(derivedCtor,baseCtors){baseCtors.forEach(baseCtor=>{Object.getOwnPropertyNames(baseCtor.prototype).forEach(name=>{letdescriptor=Object.getOwnPropertyDescriptor(baseCtor.prototype,name)Object.defineProperty(derivedCtor.prototype,name,descriptor);});});}classA{methodA(){console.log('A')}}classB{methodB(){console.log('B')}}classC{}//使用mixin我们需要这样做,因为在JS中我们不能写:classA{methodA(){console.log("A")}}classB{methodB(){console.log("B")}}classCextendsA,B{}在上面的例子中,关键部分应该是applyMixins函数。以防万一,您不完全理解它试图做什么,但您可以清楚地看到它正在访问所有类的原型属性以复制和重新分配方法和属性。这就是我们需要看清真相的地方:类只不过是已证实的原型继承模型之上的语法糖。这是否意味着我们应该停止使用类?当然不是,理解它很重要,如果我们想做一些超出类限制的事情,那么我们就不得不处理原型。JS的OOP模型缺少什么?如果我们当前的OOP模型如此薄,只是一个原型继承的抽象层,我们到底缺少什么?是什么让JS真正面向对象?查看此问题的一个好方法是查看TypeScript在做什么。该语言背后的团队通过创建可以翻译成JS的东西,无疑将JS推向了极限。这反过来又限制了他们的能力。一些当前在JS中缺失的OOP结构具有内在类型检查并且在动态类型语言中没有实际意义,这可能是它们尚未添加的原因。接口接口帮助定义一个类应该符合的API。接口的主要好处之一是我们可以定义实现相同接口的任何类的变量,然后安全地调用它的任何方法。interfaceAnimal{speak()}classDogimplementsAnimal{speak(){console.log("Woof!")}}classCatimplementsAnimal{speak(){console.log("Meau!")}}classHumanimplementsAnimal{speak(){console.log("Heydude,what'sup?")}}//如果我们在JS中有接口,我们可以安全地做:letobjects=[newDog(),newCat(),newHuman()]objects.forEach(o=>o.speak())当然,我们可以通过定义speak方法并重写它的类来实现同样的效果,但界面更清晰、更优雅。抽象类每当我尝试用我的代码进行完整的OOP时,我肯定会想念JS中的抽象类。抽象类是定义和实现方法但从不实例化的类。这是一种对可以扩展但从不直接使用的常见行为进行分组的方法。这是一个很好的资源,绝对可以在当前的JS环境中实现而无需太多努力。静态多态性静态多态性允许我们在同一个类中多次定义相同的方法,但具有不同的签名。换句话说,重复名称,但确保它接收不同的参数。现在我们有了JS的剩余参数,这允许我们有任意数量,但是,这也意味着我们必须在方法中添加额外的代码来处理这种动态性。相反,我们可以更清楚地区分方法签名,因此我们可以将相同行为的不同含义直接封装到不同的方法中。左边的版本不是有效的JS,但它提供了更清晰的代码,因此更易于阅读和理解。右边的版本是完全有效的,它更难阅读并且需要一些ES6语法。多态性通常通过查看方法中接收的参数类型来实现。但是,我们知道由于JS的工作方式,这是不可能的。我们已经对受保护的属性和方法具有公共可见性,并且我们很快获得了对方法和属性的私有可见性(通过#前缀)。我认为下一步应该是添加受保护的可见性,但是,目前还没有,如果您想拥有适当的OOP体验,我认为这三者都是必要的。受保护的属性和方法只能从类内部或其子类之一访问(与私有可见性相反,私有可见性仅限于父类)。今天和大家分享的就这些了,我是小智,我们下期再见。代码部署后可能存在的bug,无法实时获知。事后为了解决这些bug,花费了大量的时间在日志调试上。顺便推荐一个好用的bug监控工具Fundebug。原文:https://blog.bitsrc.io/whats-...每周更新交流文章。可以微信搜索“大千世界”立即阅读更新(比博文早一两篇),本文的GitHubhttps://github.com/qq449245884/xiaozhi已经收录,还有很多我的文件已经整理好了。欢迎明星和完美。面试可以参考考点。也关注公众号,后台回复福利,就可以看到福利,你懂的。