Class

  • Class
class MyClass{
//class方法
constructor(){....}
method1(){...}
method2(){...}
//在class里不需要写“,”
}

然后使用 new MyClass() 来创建具有上述列出的所有方法的新对象。
new 会自动调用 constructor() 方法,因此我们可以在 constructor() 中初始化对象。
例如:

class User {

  constructor(name) {
    this.name = name;
  }

  sayHi() {
    alert(this.name);
  }

}

// 用法:
let user = new User("John");
user.sayHi();

当 new User("John") 被调用:
1.一个新对象被创建。
2.constructor 使用给定的参数运行,并为其分配 this.name。
……然后我们就可以调用对象方法了,例如 user.sayHi。

类的方法之间没有逗号
对于新手开发人员来说,常见的陷阱是在类的方法之间放置逗号,这会导致语法错误。
不要把这里的符号与对象字面量相混淆。在类中,不需要逗号。

在 JavaScript 中,类是一种函数。
看看下面这段代码:

class User {
  constructor(name) { this.name = name; }
  sayHi() { alert(this.name); }
}

// 佐证:User 是一个函数
alert(typeof User); // function

class User {...} 构造实际上做了如下的事儿:

  1. 创建一个名为 User 的函数,该函数成为类声明的结果。该函数的代码来自于 constructor 方法(如果我们不编写这种方法,那么它就被假定为空)。
  2. 存储类中的方法,例如 User.prototype 中的 sayHi

new User 对象被创建后,当我们调用其方法时,它会从原型中获取对应的方法,因此,对象 new User 可以访问类中的方法。

  • 内部接口和外部接口
    在面向对象的编程中,属性和方法分为两组:
    1.内部接口 —— 可以通过该类的其他方法访问,但不能从外部访问的方法和属性。
    2.外部接口 —— 也可以从类的外部访问的方法和属性。

  • 在 JavaScript 中,有两种类型的对象字段(属性和方法):
    1.公共的:可从任何地方访问。它们构成了外部接口。到目前为止,我们只使用了公共的属性和方法。
    2.私有的:只能从类的内部访问。这些用于内部接口。

  • Class-类-私有的和受保护的属性和方法

受保护的属性通常以下划线 _ 作为前缀。

这不是在语言级别强制实施的,但是程序员之间有一个众所周知的约定,即不应该从外部访问此类型的属性和方法。

受保护的字段是可以被继承的
如果我们继承 class MegaMachine extends CoffeeMachine,那么什么都无法阻止我们从新的类中的方法访问 this._waterAmount 或 this._power。
所以受保护的字段是自然可被继承的。与我们接下来将看到的私有字段不同。

  • 私有的

私有属性和方法应该以 # 开头。它们只在类的内部可被访问。

例如,这儿有一个私有属性 #waterLimit 和检查水量的私有方法 #checkWater:

class CoffeeMachine {
 #waterLimit = 200;

 #checkWater(value) {
   if (value < 0) throw new Error("Negative water");
   if (value > this.#waterLimit) throw new Error("Too much water");
 }

}

let coffeeMachine = new CoffeeMachine();

// 不能从类的外部访问类的私有属性和方法
coffeeMachine.#checkWater(); // Error
coffeeMachine.#waterLimit = 1000; // Error

在语言级别,# 是该字段为私有的特殊标志。我们无法从外部或从继承的类中访问它。

私有字段与公共字段不会发生冲突。我们可以同时拥有私有的 #waterAmount 和公共的 waterAmount 字段。

例如,让我们使 waterAmount 成为 #waterAmount 的一个访问器:

class CoffeeMachine {

  #waterAmount = 0;

  get waterAmount() {
    return this.#waterAmount;
  }

  set waterAmount(value) {
    if (value < 0) throw new Error("Negative water");
    this.#waterAmount = value;
  }
}

let machine = new CoffeeMachine();

machine.waterAmount = 100;
alert(machine.#waterAmount); // Error

与受保护的字段不同,私有字段由语言本身强制执行。这是好事儿。

但是如果我们继承自 CoffeeMachine,那么我们将无法直接访问 #waterAmount。我们需要依靠 waterAmount getter/setter:

class MegaCoffeeMachine extends CoffeeMachine {
  method() {
    alert( this.#waterAmount ); // Error: can only access from CoffeeMachine
  }
}

在许多情况下,这种限制太严重了。如果我们扩展 CoffeeMachine,则可能有正当理由访问其内部。这就是为什么大多数时候都会使用受保护字段,即使它们不受语言语法的支持。
私有字段不能通过 this[name] 访问
私有字段很特别。

正如我们所知道的,通常我们可以使用 this[name] 访问字段:

class User {
  ...
  sayHi() {
    let fieldName = "name";
    alert(`Hello, ${this[fieldName]}`);
  }
}

对于私有字段来说,这是不可能的:this['#name'] 不起作用。这是确保私有性的语法限制。

  • 总结
    就面向对象编程(OOP)而言,内部接口与外部接口的划分被称为 封装

它具有以下优点:
保护用户,使他们不会误伤自己
想象一下,有一群开发人员在使用一个咖啡机。这个咖啡机是由“最好的咖啡机”公司制造的,工作正常,但是保护罩被拿掉了。因此内部接口暴露了出来。
所有的开发人员都是文明的 —— 他们按照预期使用咖啡机。但其中的一个人,约翰,他认为自己是最聪明的人,并对咖啡机的内部做了一些调整。然而,咖啡机两天后就坏了。
这肯定不是约翰的错,而是那个取下保护罩并让约翰进行操作的人的错。
编程也一样。如果一个 class 的使用者想要改变那些本不打算被从外部更改的东西 —— 后果是不可预测的。

- 可支持性
编程的情况比现实生活中的咖啡机要复杂得多,因为我们不只是购买一次。我们还需要不断开发和改进代码。

- 如果我们严格界定内部接口,那么这个 class 的开发人员可以自由地更改其内部属性和方法,甚至无需通知用户。
如果你是这样的 class 的开发者,那么你会很高兴知道可以安全地重命名私有变量,可以更改甚至删除其参数,因为没有外部代码依赖于它们。
对于用户来说,当新版本问世时,应用的内部可能被进行了全面检修,但如果外部接口相同,则仍然很容易升级。

- 隐藏复杂性
人们喜欢使用简单的东西。至少从外部来看是这样。内部的东西则是另外一回事了。
程序员也不例外。

- 当实施细节被隐藏,并提供了简单且有据可查的外部接口时,总是很方便的。
为了隐藏内部接口,我们使用受保护的或私有的属性:

  • 受保护的字段以 _ 开头。这是一个众所周知的约定,不是在语言级别强制执行的。程序员应该只通过它的类和从它继承的类中访问以 _ 开头的字段。
  • 私有字段以 # 开头。JavaScript 确保我们只能从类的内部访问它们。

目前,各个浏览器对私有字段的支持不是很好,但可以用 polyfill 解决。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容

  • 金蝶一面 Redis缓存一致性问题, 事务的几种隔离级别,如何解决脏读,幻读,不可重复读,为什么可重复读解决了幻读...
    田园牧歌_a2ee阅读 118评论 0 0
  • reduce 当你传入一个初始值的时候,reduce函数会为你遍历数组中的每一个元素;而当你不传初始值的时候,re...
    rub1cky阅读 455评论 0 0
  • 双赢思维 1、什么是双赢思维? 谈判听起来离我们很远,其实它几乎无处不在。比如,商场上怎么谈合作?部门之间发生冲突...
    41c3c60f6cd5阅读 337评论 0 0
  • 第一部分 项目介绍 (一)项目大区位 (二)项目小区位 (三)项目基本信息 (四)项目四至及周边环境 (五)周边配...
    有国才有家阅读 184评论 0 0
  • 1.内存管理 内存布局 内存管理方案(更好的简述内存管理方案相关的问题,就要明白他们的数据结构) 数据结构 ARC...
    alelaile阅读 544评论 0 0