ES5 模拟 ES6 的 Symbol 实现私有成员功能示例


Posted in Javascript onMay 06, 2020

本文实例讲述了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 来实现私有属性的目的已经达到了。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
解决FLASH需要点击激活的代码
Dec 20 Javascript
Javascript 表单之间的数据传递代码
Dec 04 Javascript
设置iframe的document.designMode后仅Firefox中其body.innerHTML为br
Feb 27 Javascript
在浏览器窗口上添加遮罩层的方法
Nov 12 Javascript
向左滚动文字 js代码效果
Aug 17 Javascript
node.js中的fs.rmdir方法使用说明
Dec 16 Javascript
js简单实现点击左右运动的方法
Apr 10 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
Nov 29 Javascript
canvas实现图像放大镜
Feb 06 Javascript
angular.js+node.js实现下载图片处理详解
Mar 31 Javascript
Bootstrap实现各种进度条样式详解
Apr 13 Javascript
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
Aug 23 Javascript
Vue 的双向绑定原理与用法揭秘
May 06 #Javascript
微信小程序中使用 async/await的方法实例分析
May 06 #Javascript
JavaScript常用工具函数大全
May 06 #Javascript
详解react组件通讯方式(多种)
May 06 #Javascript
Node.js API详解之 os模块用法实例分析
May 06 #Javascript
js实现无缝轮播图特效
May 09 #Javascript
js实现上传按钮并显示缩略图小轮子
May 04 #Javascript
You might like
利用 window_onload 实现select默认选择
2006/10/09 PHP
几种显示数据的方法的比较
2006/10/09 PHP
PHP stripos()函数及注意事项的分析
2013/06/08 PHP
php7安装yar扩展的方法详解
2017/08/03 PHP
JS弹出层的显示与隐藏示例代码
2013/12/27 Javascript
关闭页面时window.location事件未执行的原因分析及解决方案
2014/09/01 Javascript
JavaScript插件化开发教程 (三)
2015/01/27 Javascript
jQuery实现径向动画菜单效果
2015/07/17 Javascript
一波JavaScript日期判断脚本分享
2016/03/06 Javascript
js 实现数值的千分位及保存小数方法(推荐)
2016/08/01 Javascript
jquery 实现复选框的全选操作实例代码
2017/01/24 Javascript
vue使用xe-utils函数库的具体方法
2018/03/06 Javascript
JS面向对象的程序设计相关知识小结
2018/05/26 Javascript
小程序指纹验证的实现代码
2018/12/04 Javascript
解决微信小程序云开发中获取数据库的内容为空的方法
2019/05/15 Javascript
对layui初始化列表的CheckBox属性详解
2019/09/13 Javascript
Python实现对PPT文件进行截图操作的方法
2015/04/28 Python
在Python中marshal对象序列化的相关知识
2015/07/01 Python
Python实现对excel文件列表值进行统计的方法
2015/07/25 Python
Python反射用法实例简析
2017/12/22 Python
python 获取微信好友列表的方法(微信web)
2019/02/21 Python
python-xpath获取html文档的部分内容
2020/03/06 Python
Python线程协作threading.Condition实现过程解析
2020/03/12 Python
django自带的权限管理Permission用法说明
2020/05/13 Python
python 基于selectors库实现文件上传与下载
2020/12/31 Python
Fossil美国官网:Fossil手表、手袋、珠宝及配件
2017/02/01 全球购物
I.T中国官网:精选时尚设计师单品网购平台
2018/03/26 全球购物
《要下雨了》教学反思
2014/02/17 职场文书
互联网电子商务专业毕业生求职信
2014/03/18 职场文书
远程网络教育毕业生自我鉴定
2014/04/14 职场文书
应届大专生自荐书
2014/06/16 职场文书
供用电专业求职信
2014/07/07 职场文书
烟台的海导游词
2015/02/02 职场文书
坎儿井导游词
2015/02/09 职场文书
2016孝老爱亲模范事迹材料
2016/02/26 职场文书
2022漫威和DC电影上映作品
2022/04/05 欧美动漫