JavaScript 实现私有属性

2023-05-27 0 206

JavaScript 被许多人指出并并非一类程序词汇词汇,其原因有许多种不同,比如说 JavaScript 没类,无法提供更多现代的类式承继;再比如说 JavaScript 无法同时实现重要信息的暗藏,无法同时实现专有核心成员。责任编辑并并非为的是冲破以内误会(事实上本栏他们也有疑惑),而已单纯如是说三种 JavaScript 同时实现专有优点的形式,和各别的好坏。

1. 如前所述标识符规范化签订合同同时实现形式

许多标识符规范化把以换行_结尾的表达式签订合同为专有核心成员,易于同项目组开发人员的相互配合。同时实现形式如下表所示:

function Person(name){ this._name = name;}var person = new Person(Joe);

此种形式而已一类规范化签订合同,很难被冲破。所以也并没同时实现专有优点,前述标识符中的示例 person 能间接出访到 _name 优点:

alert(person._name); //Joe

2. 如前所述旋量群的同时实现形式

除此之外一类较为两极化的形式是借助 JavaScript 的旋量群优点。构造表达式内表述局部表达式和权利表达式,其示例根本无法透过权利表达式出访此表达式,如下表所示:

function Person(name){ var _name = name; this.getName = function(){ return _name; }}var person = new Person(Joe);

此种形式的缺点是同时实现了专有优点的

alert(person._name); // undefinedalert(person.getName()); //Joe

采用旋量群和权利表达式同时实现专有优点的表述和出访是许多开发人员选用的形式,Douglas Crockford 也曾在博客中提到过此种形式。但是此种形式存在一些缺陷:

专有表达式和权利表达式根本无法在构造表达式中创建。通常来讲,构造表达式的功能只负责创建新对象,方法应该共享于 prototype 上。权利表达式本质上是存在于每个示例中的,而并非 prototype 上,增加了资源占用。

3. 如前所述强引用散列表的同时实现形式

JavaScript 不支持 Map 数据结构,所谓强引用散列表形式只不过是Map模式的一类变体。单纯来讲,就是给每个示例新增一个唯一的标识符,以此标识符为 key,对应的value便是这个示例的专有优点,这对 key-value 保存在一个 Object 内。同时实现形式如下表所示:

var Person = (function() { var privateData = {}, privateId = 0; function Person(name) { Object.defineProperty(this, “_id”, { value: privateId++ }); privateData[this._id] = { name: name }; } Person.prototype.getName = function() { return privateData[this._id].name; }; return Person;}());

前述标识符的有以下几个特征:

采用自执行表达式创建 Person 类,表达式 privateData 和 privateId 被所有示例共享;privateData 用来储存每个示例的专有优点 name 的 key-value,privateId 用来分配每个示例的唯一标识符 _id;方法getName 存在于 prototype 上,被所有示例共享。

此种形式在目前 ES5 环境下,基本是最佳方案了。但是仍然有一个致命的缺陷:散列表privateData对每个示例都是强引用,导致示例无法被垃圾回收处理。如果存在大量示例必然会导致 memory leak。

造成以内问题的本质是 JavaScript 的旋量群引用,和根本无法采用字符串类型最为散列表的key值。针对这两个问题,ES6新增的WeakMap能良好的解决。

4. 如前所述 WeakMap 的同时实现形式

WeakMap 有以下特点:

支持采用对象类型作为key值;弱引用。

根据 WeakMap 的特点,便不必为每个示例都创建一个唯一标识符,因为示例本身便能作为 WeakMap 的 key。改进后的标识符如下表所示:

var Person = (function() { var privateData = new WeakMap(); function Person(name) { privateData.set(this, { name: name }); } Person.prototype.getName = function() { return privateData.get(this).name; }; return Person;}());

改进的标识符不仅仅干净了许多,所以WeakMap是一类弱引用散列表, 这意味着,如果没其他引用和该键引用同一个对象,这个对象将会被当作垃圾回收掉。解决了内存泄露的问题。

不幸的是,目前浏览器对WeakMap的支持率并不理想,投入生产环境仍然需要等待。

参考文献

WeakMap – MDN;WeakMap Objects – ES6;Private_Properties – MDN;Private instance members with weakmaps in JavaScript by Nicholas C. Zakas

举报/反馈

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务