JavaScript 对象中怎么嵌入私有成员

发布时间:2021-08-10 16:11:06 作者:Leah
来源:亿速云 阅读:129

JavaScript 对象中怎么嵌入私有成员,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

1. 为何要用私有成员(Private Members)

当你用JavaScript 创建一个对象时,可以声明值成员(value members)。 如果你打算控制对它们的读/写访问操作,可以如下声明:

var entity = {};  entity._property = "hello world"; Object.defineProperty(entity, "property", {     get: function () { return this._property; },     set: function (value) {         this._property = value;     },     enumerable: true,     configurable: true });

这样实现,你能完全控制读和写操作。问题在于_property 成员仍然可以直接访问和修改。

这也就是为何我们需要更加稳定可靠的方式,声明私有成员,它智能通过对象的方法来访问。

2. 使用闭包空间(Closure Space)

解决方法是使用闭包空间。每当内部函数 (inner fanction) 访问来自外部函数作用域的变量时,浏览器为你分配一段内存空间。有时很取巧,不过就我们的题目来讲,这算是一个***的解决方案。

我们在上个代码版本中添加这个特性:

var createProperty = function (obj, prop, currentValue)  {     Object.defineProperty(obj, prop,      {             get: function () { return currentValue; },             set: function (value) {             currentValue = value;                     },                     enumerable: true,                     configurable: true    });                     }  var entity = {};  var myVar = "hello world";createProperty(entity, "property", myVar);

示例中,createProperty 函数有一个 currentValue 变量,存在 get 和 set 方法。此变量会保存到 get 和 set 函数的闭包空间中。现在,只有这两个函数能看到和更新 currentValue 变量! 任务完成!

唯一需要警惕 caveat,警告,注意)的是源值 (myVar) 仍可访问。下面给出另一个更健壮的版本(保护 myVar 变量):

var createProperty = function (obj, prop) {     var currentValue = obj[prop];     Object.defineProperty(obj, prop, {         get: function () { return currentValue; },         set: function (value) {             currentValue = value;         },         enumerable: true,         configurable: true     }); }  var entity = {     property: "hello world" };  createProperty(entity, "property");

采用该函数, 即便源值都销毁(destructed,注:意思是不能直接赋值)了。到此大功告成了!

3. 性能考虑Performance Considerations

现在咱们看看性能。

很明显,比起一个简单的变量,闭包空间,甚或(对象)属性要慢的多,且更消耗资源。这就是本文更多关注普通方式和闭包空间机制差异的原因。

为证明闭包空间机制并不比标准方式更消耗资源, 我写了下面代码做个基准测试:

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head>     <title></title> </head> <style>     html {         font-family: "Helvetica Neue", Helvetica;     } </style> <body>     <div id="results">Computing...</div>     <script>         var results = document.getElementById("results");         var sampleSize = 1000000;         var opCounts = 1000000;          var entities = [];          setTimeout(function () {             // Creating entities             for (var index = 0; index < sampleSize; index++) {                 entities.push({                     property: "hello world (" + index + ")"                 });             }              // Random reads             var start = new Date().getTime();             for (index = 0; index < opCounts; index++) {                 var position = Math.floor(Math.random() * entities.length);                 var temp = entities[position].property;             }             var end = new Date().getTime();              results.innerHTML = "<strong>Results:</strong><br>Using member access: <strong>" + (end - start) + "</strong> ms";         }, 0);          setTimeout(function () {             // Closure space =======================================             var createProperty = function (obj, prop, currentValue) {                 Object.defineProperty(obj, prop, {                     get: function () { return currentValue; },                     set: function (value) {                         currentValue = value;                     },                     enumerable: true,                     configurable: true                 });             }             // Adding property and using closure space to save private value             for (var index = 0; index < sampleSize; index++) {                 var entity = entities[index];                  var currentValue = entity.property;                 createProperty(entity, "property", currentValue);             }              // Random reads             var start = new Date().getTime();             for (index = 0; index < opCounts; index++) {                 var position = Math.floor(Math.random() * entities.length);                 var temp = entities[position].property;             }             var end = new Date().getTime();              results.innerHTML += "<br>Using closure space: <strong>" + (end - start) + "</strong> ms";         }, 0);          setTimeout(function () {             // Using local member =======================================             // Adding property and using local member to save private value             for (var index = 0; index < sampleSize; index++) {                 var entity = entities[index];                  entity._property = entity.property;                 Object.defineProperty(entity, "property", {                     get: function () { return this._property; },                     set: function (value) {                         this._property = value;                     },                     enumerable: true,                     configurable: true                 });             }              // Random reads             var start = new Date().getTime();             for (index = 0; index < opCounts; index++) {                 var position = Math.floor(Math.random() * entities.length);                 var temp = entities[position].property;             }             var end = new Date().getTime();              results.innerHTML += "<br>Using local member: <strong>" + (end - start) + "</strong> ms";         }, 0);      </script> </body> </html>

我创建了一百万个对象,都有属性成员。要完成下面三个测试:

测试结果参见下面表格和图表:

JavaScript 对象中怎么嵌入私有成员

JavaScript 对象中怎么嵌入私有成员

我们发现,闭包空间实现总是快于常规实现,根据浏览器的不同,还可以做进一步的性能优化。

Chrome 上的性能表现低于预期。或许存在 bug,因此,为确认(存在 bug),我联系了 Google 项目组,描述发生的症状。还有,如果你打算测试在 Microsoft Edge &mdash;微软新发布的浏览器,在windows10 中默认安装&mdash;中的性能表现,你可以点击下载 。

然而,如果仔细研究,你会发现,使用闭包空间或属性比直接访问变量成员要10倍左右。 因此,使用要恰当且谨慎。

JavaScript 对象中怎么嵌入私有成员

4. 内存占用(Memory Footprint)

我们也得验证该技术不会消耗过多内存。为测试内存占用基准情况,我写了下面代码段:

直接属性引用版本(Reference Code)

var sampleSize = 1000000;  var entities = [];  // Creating entities for (var index = 0; index < sampleSize; index++) {     entities.push({             property: "hello world (" + index + ")" });}  常规方式版本(Regular Way,get/set)  var sampleSize = 1000000;  var entities = [];  // Adding property and using local member to save private value for (var index = 0; index < sampleSize; index++) {     var entity = {};      entity._property = "hello world (" + index + ")";     Object.defineProperty(entity, "property", {         get: function () { return this._property; },         set: function (value) {             this._property = value;         },         enumerable: true,         configurable: true     });      entities.push(entity); }  闭包空间版本(Closure Space Version)  var sampleSize = 1000000;  var entities = [];  var createProperty = function (obj, prop, currentValue) {     Object.defineProperty(obj, prop, {         get: function () { return currentValue; },         set: function (value) {             currentValue = value;         },         enumerable: true,         configurable: true     }); }  // Adding property and using closure space to save private value for (var index = 0; index < sampleSize; index++) {     var entity = {};      var currentValue = "hello world (" + index + ")";     createProperty(entity, "property", currentValue);      entities.push(entity); }

之后,我(在三个主流浏览器上)运行所有的三段代码,启动(浏览器)内嵌的内存性能分析器(本示例中使用 F12 工具条):

JavaScript 对象中怎么嵌入私有成员

我计算机上运行的结果如下图表:

JavaScript 对象中怎么嵌入私有成员

就闭包空间和常规方式,只有 Chrome上,闭包空间(内存占用)表现稍好,在 IE11 和 Firefox上占用内存反而增多,但是浏览器的比较结果e&mdash;对于现代浏览器,用户很可能不会在意这点差别。

更多 JavaScript 实践

或许你会吃惊,微软提供了一批有关开源 Javascript 主题的免费学习材料, 我们正在发起一个任务,关于创建更多 Microsoft Edge 来临 系列。 查看我的文章:

或者我们团队系列:

关于JavaScript 对象中怎么嵌入私有成员问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

推荐阅读:
  1. JavaScript 私有成员
  2. JavaScript的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

javascript

上一篇:Linux中怎么配置Jython环境

下一篇:WordPress中怎么利用Markdown提高工作效率

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》