[译] ECMAScript 类 —— 定义私有属性
栏目: JavaScript · 发布时间: 5年前
内容简介:像往常一样,我们将从一些理论知识开始介绍。ES 的类是 JavaScript 中新的语法糖。它提供了一种简洁的编写方法,并且实现了与我们使用原型链相同的功能。唯一的区别是,它看起来更像是面向对象编程了,而且,如果你是 C# 或 Java 开发者,感觉会更友好。有人可能会说它们不适合 JavaScript,但对我来说,使用类或 ES5 的原型都没有问题。它提供了一种更简单的方式来封装和定义多个属性,这些属性可以在具体的实例对象上被访问到。事实上,我们可以通过类的方式编写更少的代码来实现更多的功能。有了类,Ja
像往常一样,我们将从一些理论知识开始介绍。ES 的类是 JavaScript 中新的语法糖。它提供了一种简洁的编写方法,并且实现了与我们使用原型链相同的功能。唯一的区别是,它看起来更像是面向对象编程了,而且,如果你是 C# 或 Java 开发者,感觉会更友好。有人可能会说它们不适合 JavaScript,但对我来说,使用类或 ES5 的原型都没有问题。
它提供了一种更简单的方式来封装和定义多个属性,这些属性可以在具体的实例对象上被访问到。事实上,我们可以通过类的方式编写更少的代码来实现更多的功能。有了类,JavaScript 正朝着面向对象的方式发展,通过使用类,我们可以实现面向对象编程,而不是函数式编程。不要误解我的意思,函数式编程并不是一件坏事,实际上,这是一件好事,它也有一些优于类的好处,但这应该是另一篇文章要讨论的主题。
举一个实际的例子,每当我们想在应用程序中定义来自真实世界的事物时,我们都会使用一个类来描述它。例如,building、car、motorcycle……它们代表一类真实的事物。
可访问范围
在后端语言中,我们有访问修饰符或可见性级别,如 public
、 private
、 protected
、 internal
、 package
……不幸的是,JavaScript 仅以自己的方式支持前两种方法。它不通过编写访问修饰符( public
或 private
)来声明字段,JavaScript 在某种程度上假定所有的区域都是公共的,这就是我写这篇文章的原因。
注意,我们有一种方法可以在类上声明私有和公共的字段,但是这些字段声明方法还是实验性的特性,因此还不能安全的使用它。
class SimCard { number; // public field type; // public field #pinCode; // private field } 复制代码
如果没有像 Babel 这样的编译器,就不支持使用上面这样的字段声明方式。
定义私有属性 —— 封装
封装是编程中的一个术语,比如它用来描述某个变量是受保护的或对外部是不可见的。为了保持数据私有并且只对内部可见,我们需要 封装 它。在本文中,我们将使用几种不同的方法来封装私有数据。让我们开始吧。
1. 习惯约定
这种方式只是假定数据或变量的 private
状态。实际上,它们是公开的,外部可以访问。我了解到的两种最常见的定义私有状态的习惯约定是 $
和 _
前缀。如果某个变量以这些符号作为前缀(通常在整个应用中会规定使用某一个),那么该变量应该作为非公共属性来处理。
class SimCard { constructor(number, type, pinCode) { this.number = number; this.type = type; // 这个属性被定义为私有的 this._pinCode = pinCode; } } const card = new SimCard("444-555-666", "Micro SIM", 1515); // 这里,我们将访问私有的 _pinCode 属性,这并不是我们预期的行为 console.log(card._pinCode); // 输出 1515 复制代码
2. 闭包
闭包对于控制变量的可访问性非常有用。它被 JavaScript 开发者使用了几十年。这种方法为我们提供了真正的私有性,数据对外部来说是无法访问的,它只能被内部访问。这里我们要做的是在类构造函数中创建局部变量,并用闭包捕获它们。要实现这个效果,方法必须定义在实例上,而不是在原型链上。
class SimCard { constructor(number, type, pinCode) { this.number = number; this.type = type; let _pinCode = pinCode; // 这个属性被定义为私有的 this.getPinCode = () => { return _pinCode; }; } } const card = new SimCard("444-555-666", "Nano SIM", 1515); console.log(card._pinCode); // 输出 undefined console.log(card.getPinCode()); // 输出 1515 复制代码
3. Symbols 和 Getters
Symbol 是 JavaScript 中一种新的基本数据类型。它是在 ECMAScript 6 中引入的。 Symbol()
返回的每个值都是唯一的,这种类型的主要目的是用作对象属性的标识符。
由于我们的意图是在类定义的外部创建 Symbol 变量,但也不是全局的,所以引入了模块。这样,我们能够在模块内部创建私有字段,将它们定义到类的构造函数中,并通过 getter
返回 Symbol 变量对应的值。注意,我们可以使用在原型链上创建的方法来代替 getter
。我选择了 getter
方法,因为这样我们就不需要调用函数来获取值了。
const SimCard = (() => { const _pinCode = Symbol('PinCode'); class SimCard { constructor(number, type, pinCode) { this.number = number; this.type = type; this[_pinCode] = pinCode; } get pinCode() { return this[_pinCode]; } } return SimCard; })(); const card = new SimCard("444-555-666", "Nano SIM", 1515); console.log(card._pinCode); // 输出 undefined console.log(card.pinCode); // 输出 1515 复制代码
这里需要指出的一点是 Object.getOwnPropertySymbols
方法,此方法可用于访问我们用来保存私有属性的 Symbol 变量。上面的类中的 _pinCode
值就可以这样被获取到:
const card = new SimCard("444-555-666", "Nano SIM", 1515); console.log(card[Object.getOwnPropertySymbols(card)[0]]); // 输出 1515 复制代码
4. Map 和 Getters
ECMAScript 6 还引入了 Map
和 WeakMap
。它们以键值对的形式存储数据,这使得它们非常适合存储我们的私有变量。在我们的示例中, Map
被定义在模块的内部,并且在类的构造函数中设置每个私有属性的键值。这个值被类的 getter
引用,同样,我们不需要调用函数来获取值。另外,请注意,考虑到 Map
本身的结构,我们不需要为每个私有属性定义 Map
映射。
const SimCard = (() => { const _privates = new Map(); class SimCard { constructor(number, type, pinCode, pukCode) { this.number = number; this.type = type; _privates.set('pinCode', pinCode); _privates.set('pukCode', pukCode); } get pinCode() { return _privates.get('pinCode'); } get pukCode() { return _privates.get('pukCode'); } } return SimCard; })(); const card = new SimCard("444-555-666", "Nano SIM", 1515, 45874589); console.log(card.pinCode); // 输出 1515 console.log(card.pukCode); // 输出 45874589 console.log(card._privates); // 输出 undefined 复制代码
注意,在这种方法中,我们也可以使用普通对象而不是 Map
,并在构造函数中动态地为其分配值。
以上所述就是小编给大家介绍的《[译] ECMAScript 类 —— 定义私有属性》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 私有属性的实现
- 协议中的私有属性
- JavaScript 新语法详解:Class 的私有属性与私有方法
- 外部调用类的私有属性
- JavaScript Class(类) 中的 Private(私有) 和 Public(公有) 属性
- TC39 在 GitHub 通过一条 EMCAScript 私有属性的草案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
基于MVC的JavaScript Web富应用开发
麦卡劳(Alex MacCaw) / 李晶、张散集 / 电子工业出版社 / 2012-5 / 59.00元
《JavaScript Web 富应用开发》Developing JavaScript Web Applications是 Alex MacCaw 的新作(由O'Reilly出版发行),本书系统而深入的讲解了如何使用最前沿的Web技术构建下一代互联网富应用程序。作者 Alex MacCaw 是一名Ruby/JavaScript 程序员,在开源社区中很有名望,是Spine框架的作者,同时活跃在纽约、......一起来看看 《基于MVC的JavaScript Web富应用开发》 这本书的介绍吧!