[译] ECMAScript 类 —— 定义私有属性
栏目: JavaScript · 发布时间: 6年前
内容简介:像往常一样,我们将从一些理论知识开始介绍。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 私有属性的草案
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Powerful
Patty McCord / Missionday / 2018-1-25
Named by The Washington Post as one of the 11 Leadership Books to Read in 2018 When it comes to recruiting, motivating, and creating great teams, Patty McCord says most companies have it all wrong. Mc......一起来看看 《Powerful》 这本书的介绍吧!