ES5 中模仿 ES6 的 Symbol 完成私有成员

ES6 中有类语法,定义类变得简朴了

class Person {
    constructor(name) {
        this._name = name;
    }
    
    get name() {
        return this._name;
    }
}

但是,并没有供应私有属性。比方上面的 Person 实际上是愿望在组织的时刻传入 name,以后不允许修改了。不过,因为没有私有属性,所以不免有人会如许干:

Person james = new Person("James");
james._name = "Tom";        // God Save Me

不过,假如想定义私有成员,也有变通的体式格局,比方广为留传的 Symbol 大法

var Person = (function() {
    let _name = Symbol();
    class Person {
        constructor(name) {
            this[_name] = name;
        }
        
        get name() {
            return this[_name];
        }
    }
    return Person;
})();

实在质在于匿名函数中的 Symbol 实例 _name 是局部变量,在外部不可接见。而 Symbol 因为本身的唯一性特性,也没法再造一个雷同的出来,所以就模仿出来一个私有成员了。

按照此思绪,在 ES5 中实在也很轻易模仿私有成员。局部变量是很轻易做到的,在函数范围内 letvar 是一样的结果。问题在于模仿 Symbol 的唯一性。

ES5 没有 Sybmol,属性称号只多是一个字符串,假如我们能做到这个字符串不可预感,那末就基础到达目标。要到达不可预期,一个随机数基础上就处理了。

var Person = (function() {
    var _name = "00" + Math.random();
    function Person(name) {
        this[_name] = name;
    }
    
    Object.defineProperty(Person.prototype, "name", {
        get: function() {
            return this[_name];
        }
    });

    return Person;
})();

假如这个顺序在 Web 页面中加载,那末每次革新页面 _name 的值都邑差别,但并不会影响顺序的逻辑,外部顺序不会涌现任何不适。

但是与 Symbol 计划比拟,它的问题在于这个 _name 的值不会像 Symbol 一样会隐蔽起来,在控制台能够用很多种方法把它找出来——当然在调试阶段如许做也没什么不能够。在开辟阶段这个值仍然是不可预感的。

关于单个私有属性的状况,有人会找到私有 Key 的规律,比方上面的私有 Key 就是以 "000." 最先的,遍历对象属性很轻易找出来。在多个私有 Key 的状况下,也能够经由过程一些技术手段来找,比方

function getPersonNameKey() {
    var v = "" + Math.random();
    var p = new Person(v);
    for (var k in p) {
        if (p[k] === v) {
            return k;
        }
    }
}

但这些都是后话,做起来太费力,常人不会这么干。况且 Symbol 也是能够遍历的(经由过程 Object.getOwnPropertySymbols()),完全能够以一样的方法来猎取私有 Key。

综上,ES5 中模仿 Symbol 来完成私有属性的目标已到达了。

    原文作者:边城
    原文地址: https://segmentfault.com/a/1190000003488631
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞