视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
js中私有成员的全面解析(附代码)
2020-11-27 19:32:25 责编:小采
文档


JavaScript 中虽然约定 _ 前缀的是私有,那也只是君子之约,它实质上仍然不是私有。君子之约对人有效,计算机又不知道你有这个约定……。但是,如果 JavaScript 真的实现了私有成员,那么计算机就知道了,_layoutMap() 是个私有方法,应该调用本类中的定义,而不是去寻找子类中的定义。

解决当下的私有化问题

JavaScript 当下没有私有成员,但是我们又需要切时有效地解决私有成员问题,怎么办?当然有办法,用 Symbol 和闭包来解决。

注意,这里的闭包不是指导在函数函数中生成闭包,请继续往下看

首先搞清楚,我们变通的看待这个私有化问题 —— 就是让祖先类调用者在调用某个方法的时候,它不会先去子类中寻找。这个问题从语法上解决不了,JavaScript 就是要从具体的实例从后往前去寻找指定名称的方法。但是,如果找不到这个方法名呢?

之所以能找到,因为方法名是字符串。一个字符串在全局作用域内都表示着同样的意义。但是 ES2015 带来了 Symbol,它必须实例化,而且每次实例化出来一定代表着不同的标识 —— 如果我们将类定义在一个闭包中,在这个闭包中声明一个 Symbol,用它来作为私有成员的名称,问题就解决了,比如

const MapView = (() => {
 const _layoutMap = Symbol();

 return class MapView extends BaseView {
 layout() {
 super.layout();
 this[_layoutMap]();
 }

 [_layoutMap]() {
 console.log("MapView layout map");
 }
 }
})();

const BusinessView = (() => {
 const _layoutForm = Symbol();
 const _layoutMap = Symbol();

 return class BusinessView extends MapView {
 layout() {
 super.layout();
 this[_layoutForm]();
 this[_layoutMap]();
 }

 [_layoutForm]() {
 // ....
 }

 [_layoutMap]() {
 console.log("BusinessView layout map");
 }
 }
})();

而现代基于模块的定义,甚至连闭包都可以省了(模块系统会自动封闭作用域)

const _layoutMap = Symbol();

export class MapView extends BaseView {
 layout() {
 super.layout();
 this[_layoutMap]();
 }

 [_layoutMap]() {
 console.log("MapView layout map");
 }
}
const _layoutForm = Symbol();
const _layoutMap = Symbol();

export class BusinessView extends MapView {
 layout() {
 super.layout();
 this[_layoutForm]();
 this[_layoutMap]();
 }

 [_layoutForm]() {
 // ....
 }

 [_layoutMap]() {
 console.log("BusinessView layout map");
 }
}

改革过后的代码就可以按预期输出了:

BaseView Layout
MapView layout map
BusinessView layout map

下载本文
显示全文
专题