写点什么

JS class 并不只是简单的语法糖!

作者:掘金安东尼
  • 2022 年 7 月 19 日
  • 本文字数:1804 字

    阅读完需:约 6 分钟

JS class 并不只是简单的语法糖!

在很早以前,写过一篇文章 《“类”设计模式和“原型”设计模式——“复制”和“委托”的差异》 ,大致意思就是说:代码复用,也就是继承、重写,有两种思路:1. 面向对象的类继承;2. 基于 JavaScript 原型链的原型继承;前者的主要特点是:复制,通俗来说就是把变量、属性再复制一份,后者的主要特点是:委托,通过属性的查找来实现的。


后来呢,深入了解 JavaScript 高级程序设计中的继承,包括构造函数继承、原型继承、组合继承、寄生组合继承,都有各自的缺点。


本瓜特别记住:维基对 JavaScript 起源的解释


JavaScript 的语言设计主要受到了Self(一种基于原型的编程语言)和Scheme(一门函数式编程语言)的影响。在语法结构上它又与C语言有很多相似。


最后,我的小结呢就是:JavaScript 本身的设计就是“通过原型委托”来实现代码复用的,结果 ES6 搞出了个 class 作为语法糖,其本身还是基于原型链,但又是为了实现面向对象,面向对象是基于 class 类那种“复制”来实现代码复用。


类 和 原型,是两种不同的东西,JS class 将二者混在了一起,别不别扭?


后来也看到一些文章说在 JS 中使用 class 类会造成一些困扰,比如这篇:https://medium.com/giant-machines/stop-using-javascript-classes-d0b6890ef097,所以更加坚定要减少使用 class 。


而实际上,本篇题目是:JS class 并不只是简单的语法糖,所以,本篇并不是为了说它不好,而是要说它的好的!


来吧,展翅!


class 第一个好:私有变量

如果不用 class , 还有什么更优雅的方法实现以下子类的私有变量吗?


class Person {  constructor(firstName, lastName) {    this.firstName = firstName;    this.lastName = lastName;  } // Person.constructor   get FullName () {    return this.firstName + " " + this.lastName;  } } // Personclass Employee extends Person {   #salary;   constructor(firstName, lastName, salary) {    super(firstName, lastName);    this.salary = salary;  }   get salary() {    return this.#salary;  }   set salary(salary) {    this.#salary = salary;    console.log("Salary changed for " + this.fullName + " : $" + this.salary);  } } // Employee
复制代码


设想下,我们用原型链的思路模拟(对象):


const Person = {  set givenName(givenName) {    this._givenName = givenName;  },  set familyName(familyName) {    this._familyName = familyName;  },  get fullName() {    return `${this._givenName} ${this._familyName}`;  }};
const test = Person; // 这里假设用 对象 模拟 类test.givenName = "Joe";test.familyName = "Martinez";console.log("test.fullName", test.fullName); // Joe Martinezconsole.log("test.givenName", test.givenName); // undefinedconsole.log("test._givenName", test._givenName); // Joe
复制代码


没有实现私有属性 _givenName


而 class 可以将值存为私有,使得对象外部不能修改:


代码示例可参考:javascript-classes-are-not-just-syntactic-sugar

class 第二个好:super 继承

class 可以通过 super 更优雅的实现继承、和重写,比如:


class Cash {   constructor() {    this.total = 0;  }   add(amount) {    this.total += amount;    if (this.total < 0) this.total = 0;  } } // Cashclass Nickles extends Cash {   add(amount) {    super.add(amount * 5);  } } // Nickles
复制代码


如果是按照老样子,原型链,它可能是这样的:


const Cash = function() {  this.total = 0;}; // CashCash.prototype = {  add : function(amount) {    this.total += amount;    if (this.total < 0) this.total = 0;  }  }; // Cash.prototypeconst Nickles = function() {  Object.assign(this, new Cash());    this.add = function(amount) {    Cash.add.apply(this, amount);  };  } // Nickles
复制代码


读起来有点乱,this 指来指去,还有在构造函数中手动做的 assign 操作,这会增加代码执行耗时。


综上两点,JS class 还是非常有使用它的价值的,不用逃避,把它用在合适的场景,肯定会发现其魅力~~




OK,以上便是本篇分享。点赞关注评论,为好文助力👍

我是掘金安东尼 🤠 100 万阅读量人气前端技术博主 💥 INFP 写作人格坚持 1000 日更文 ✍ 关注我,陪你一起度过漫长编程岁月 🌏

发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022.07.14 加入

社会我瓜哥,人狠话不多😎 微信 anthony1453,加我交个朋友😎 正联合【机械工业出版社】出版《程序员成长手册》,敬请期待😎 真正的大师,永远怀着一颗学徒的心(易)😎

评论

发布
暂无评论
JS class 并不只是简单的语法糖!_JavaScript_掘金安东尼_InfoQ写作社区