es6 类的私有属性_请停止在JavaScript中使用类

多年来,OOP(面向对象编程)是软件工程中的事实上的标准。类,多态性,继承和封装的概念主导了开发过程,并对其产生了革命性的影响。但是所有内容都有有效期限,其中包括编程范例。在本文中,我将讨论为什么首先引入类,为什么在JavaScript中使用类是一个坏主意,以及一些替代方法。

0f7b4d22ad4d906d55672739672930a1.png

我不会谈论OOP为何逐渐消失,但是你可以查看这篇很棒的文章以获取更多信息。

这篇很棒的文章:https://medium.com/better-programming/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7


ES6之前的classes

即使自ES6(ECMAScript 2015)起将class关键字添加到JavaScript中,人们仍在使用类。实现的方法是构造函数和原型委托。为了确切地说明我的意思,我将在ES5和ES6环境中实现相同的类。考虑一个继承自 CarCarSportsCar 类。两者都有品牌( make )、型号( model )属性和启动方式( start ),但SportsCar还有涡轮增压( turbocharged )属性,并覆盖启动方式(start)。

// "class" 声明function Car(make, model) {  this.make = make;  this.model = model;}// 启动方法Car.prototype.start = function() {  console.log('vroom');}// 覆盖toString方法Car.prototype.toString = function() {  console.log('Car - ' + this.make + ' - ' + this.model);}// 继承实例function SportsCar(make, model, turbocharged) {  Car.call(this, make, model);  this.turbocharged = turbocharged;}// 实际继承逻辑SportsCar.prototype = Object.create(Car.prototype);SportsCar.prototype.constructor = SportsCar;// 覆盖启动方法SportsCar.prototype.start = function() {  console.log('VROOOOM');}// 现在测试课程 classesvar car = new Car('Nissan', 'Sunny');car.start(); // vroomconsole.log(car.make); // Nissanvar sportsCar = new SportsCar('Subaru', 'BRZ', true);sportsCar.start(); // VROOOOMconsole.log(car.turbocharged); // true

你可能已经猜到了,Car(第2行)和 SportsCar(第18行)函数是构造函数。使用此关键字定义属性,并使用 new 创建对象本身。如果你不熟悉 prototype,则这是每个JS对象都必须委派常见行为的特殊属性。例如,数组对象的原型具有你可能熟知的函数:map,forEach,find等。字符串原型具有功能replace,substr等。

在第33行上创建Car对象之后,可以访问其属性和方法。从第34行开始的调用导致以下操作:

  1. JS引擎要求 car 对象提供一个键为 start 的值。
  2. 对象回应说它没有这样的值。
  3. JS引擎向 car.prototype 对象询问以键 start 开头的值。
  4. car.prototype 返回JS引擎立即执行的 start 函数。

访问makemodel属性的操作类似,只是它们是直接在汽车对象上定义的,而不是原型。

继承有点棘手,它在第24-25行处理。这里最重要的函数是 Object.create 函数,它接受一个对象并返回一个全新的对象,其原型设置为作为参数传递的对象。现在,如果JS引擎在 sportsCar 对象或 sportsCar.prototype 上没有找到一个值,它将查阅 sportsCar.prototype.prototype Car 对象的原型。

ES6 Class关键字

随着2015年ES6的发布,人们期待已久的 class 关键字出现在JavaScript中。这是应社区的多次要求而做的,因为人们对来自面向对象的语言感到不适应。但他们忽略了一个重要的问题。

JavaScript不知道什么是类

JavaScript不是一门面向对象的语言,它不是被设计成这样的语言,类的概念绝对不适用于它。虽然JS中的所有内容确实都是对象,但这些对象与Java或C#中的对象不同。在JS中,对象只是具有某种复杂查找过程的Map数据结构。就是这样。当我说一切都是对象时,我是说真的:甚至函数都是对象。你可以通过以下代码片段进行检查:

function iAmAnObject() {}console.log(iAmAnObject.name); // iAmAnObjectconsole.log(Object.keys(iAmAnObject)); // Array []

好的,这一切都很好,但是 class 关键字如何工作呢?很高兴你问。你还记得前面的 CarSportsCar 示例吗?好吧,class 关键字只是最重要的语法糖。换句话说,类在概念上产生相同的代码,并且仅用于美学和可读性目的。正如我之前所承诺的,这是ES6中这些相同类的示例:

class Car {  constructor(make, model) {    this.make = make;    this.model = model;  }    start() {    console.log('vroom');  }    toString() {    console.log(`Car - ${this.make} - ${this.model}`);  }}class SportsCar extends Car {  constructor(make, model, turbocharged) {    super(make, model);    this.turbocharged = turbocharged;  }    start() {    console.log('VROOOOM');  }}// 实际用法保持不变var car = new Car('Nissan', 'Sunny');car.start(); // vroomconsole.log(car.make); // Nissanvar sportsCar = new SportsCar('Subaru', 'BRZ', true);sportsCar.start(); // VROOOOMconsole.log(car.turbocharged); // true

这些示例相同,并且产生相同的结果,有趣的是,它们在后台生成(几乎)相同的代码。

为什么不?

现在,你应该了解JS中的类是什么以及它们如何工作。现在,凭借所有这些知识,我可以解释为什么在JS中使用类是一个坏主意。

  1. 绑定问题。由于类构造函数与这个关键字密切打交道,它可能会引入潜在的绑定问题,特别是当你试图将你的类方法作为回调传递给外部例程时(你好,React开发人员)。
  2. 性能问题。由于类的实现,众所周知,它们很难在运行时进行优化。虽然目前我们享受着高性能的机器,但摩尔定律正在逐渐消失的事实可以改变这一切。
  3. 私有变量。首先,私有变量的最大优点和主要原因之一就是类在JS中不存在。
  4. 严格的层次结构。类直接引入了从上到下的顺序,使得更改更难实现,这在大多数JS应用程序中是不可接受的。
  5. 因为React团队会告诉你不要这样做。虽然他们还没有明确废弃基于类的组件,但很可能在不久的将来就会废弃。

所有这些问题都可以通过JS对象和原型委托得到缓解。 JS提供了这么多类所能做的事情,但大多数开发者却对此视而不见。如果你想真正掌握JS,你需要接受它的理念,摆脱教条式的类思维。

61b853e94a21402455834e888594333f.png

来源:https://medium.com/javascript-in-plain-english,作者:Michael Krasnov:翻译:公众号《前端全栈开发者》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值