4
文章封面

模拟实现私有变量(面试加分项)

复制// 私有变量的实现
// 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;
    }
}

评论

表情

推荐阅读