模拟实现私有变量(面试加分项)
```js // 私有变量的实现 // v1. 基础实现 class Example { constructor(name){ this._private = name; }
getName(){
return this._private;
}
}
let ex = new Example('private1'); console.log(ex.getName(), ex._private); // private private let ex1 = new Example('private2'); console.log(ex1.getName(), ex1._private); // private private
// TODO: 主要问题 // 1. 外部可以访问和修改 // 2. 语言没有配合的机制,for In可以枚举出来 // 3. 命名冲突
// v2. 使用闭包来实现 // v2.1 class Example02 { constructor(name){ let _private = ''; _private = name;
this.getName = function () {
return _private;
}
}
} let ex01 = new Example02('private1'); console.log(ex01.getName(), ex01._private); // private private let ex02 = new Example02('private2'); console.log(ex02.getName(), ex02._private); // private private
// 优点:1. 没有命名冲突, 2.外部无法直接访问和修改 // TODO: 缺点 // 1. constructor 的逻辑变得复杂。构造函数应该只做对象初始化的事情,现在为了实现私有变量,必须包含部分方法的实现,代码组织上略不清晰。 // 2. 方法存在于实例,而非原型上,子类也无法使用 super 调用 // 3. 构建增加一点点开销
// v2.2 代码优化 const Example03 = (function () { let _private = '';
class Example03 {
constructor() {
_private = 'private';
}
getName(){
return _private;
}
}
return Example03;
})();
let ex3 = new Example03(); console.log(ex3.getName(), ex3._private) // private undefined // 优点: 1. 没有命名冲突, 2. 外部无法访问和修改 // TODO: 缺点:1. 写法复杂 2. 构建开销
// v3. 使用Symbol来实现 const Example4 = (function () { // 每个Symbol实际上都是唯一的 let _private = Symbol('private');
class Example4 {
constructor(props) {
this[_private] = 'private';
}
getName(){
return this[_private];
}
}
return Example4;
})();
// 优点: 1.没有命名冲突 2.外部无法访问和修改 3. 没有性能损失 // 缺点: 写法稍微复杂,兼容性还好
// v4. 使用WeakMap实现 const _private = new WeakMap();
class Example5 { constructor(){ _private.set(this, 'private'); }
getName(){
return _private.get(this);
}
}
let ex5 = new Example5(); console.log(ex5.getName(), ex5.name)
// 上面的代码封装 const Example5 = (function () { const _private = new WeakMap();
class Example5{
constructor(){
_private.set(this, 'private');
}
getName(){
return _private.get(this);
}
}
return Example5;
})();
// v5. 最新提案 class Point {
#x;
#y;
constructor(x, y){
this.#x = x;
this.#y = y;
}
equals(point){
return this.#x === point.#x && this.#y === point.#y;
}
} ```