前言
在阅读 《ECMAScript 6 入门》的时候,零散的看到有私有变量的实现,所以在此总结一篇。
1. 约定
实现
class Example { constructor() { this._private = 'private'; } getName() { return this._private }}var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex._private); // private
优点
写法简单 调试方便 兼容性好缺点
外部可以访问和修改 语言没有配合的机制,如 for in 语句会将所有属性枚举出来 命名冲突2. 闭包
实现一
/** * 实现一 */class Example { constructor() { var _private = ''; _private = 'private'; this.getName = function() {return _private} }}var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex._private); // undefined
优点
无命名冲突 外部无法访问和修改缺点
constructor 的逻辑变得复杂。构造函数应该只做对象初始化的事情,现在为了实现私有变量,必须包含部分方法的实现,代码组织上略不清晰。 方法存在于实例,而非原型上,子类也无法使用 super 调用 构建增加一点点开销实现二
/** * 实现二 */const Example = (function() { var _private = ''; class Example { constructor() { _private = 'private'; } getName() { return _private; } } return Example;})();var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex._private); // undefined
优点
无命名冲突 外部无法访问和修改缺点
写法有一点复杂 构建增加一点点开销3. Symbol
实现
const Example = (function() { var _private = Symbol('private'); class Example { constructor() { this[_private] = 'private'; } getName() { return this[_private]; } } return Example;})();var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex.name); // undefined
优点
无命名冲突 外部无法访问和修改 无性能损失缺点
4. WeakMap
实现
/** * 实现一 */const _private = new WeakMap();class Example { constructor() { _private.set(this, 'private'); } getName() { return _private.get(this); }}var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex.name); // undefined
如果这样写,你可能觉得封装性不够,你也可以这样写:
/** * 实现二 */const Example = (function() { var _private = new WeakMap(); // 私有成员存储容器 class Example { constructor() { _private.set(this, 'private'); } getName() { return _private.get(this); } } return Example;})();var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex.name); // undefined
新闻热点
疑难解答