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 相关文章推荐
用js 让图片在 div或dl里 居中,底部对齐
Jan 21 Javascript
JavaScript通过prototype给对象定义属性用法实例
Mar 23 Javascript
学习JavaScript设计模式之代理模式
Jan 12 Javascript
浅析Jquery操作select
Dec 13 Javascript
JavaScript数据结构之二叉树的删除算法示例
Apr 13 Javascript
Vue不能检测到Object/Array更新的情况的解决
Jun 26 Javascript
JS实现的JSON序列化操作简单示例
Jul 02 Javascript
简单通过settimeout看javascript的运行机制
May 10 Javascript
微信小程序实现Swiper轮播图效果
Nov 22 Javascript
JS实现压缩上传图片base64长度功能
Dec 03 Javascript
Openlayers实现测量功能
Sep 25 Javascript
原生js实现自定义滚动条组件
Jan 20 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
德生9700DX电路分析
2021/03/02 无线电
php mysql索引问题
2008/06/07 PHP
Yii框架form表单用法实例
2014/12/04 PHP
php对关联数组循环遍历的实现方法
2015/03/13 PHP
PHP文件缓存类实现代码
2015/10/26 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
IE DOM实现存在的部分问题及解决方法
2009/07/25 Javascript
javascript 文章截取部分无损html显示实现代码
2010/05/04 Javascript
jQuery Animation实现CSS3动画示例介绍
2013/08/14 Javascript
jQuery列表拖动排列具体实现
2013/11/04 Javascript
web前端设计师们常用的jQuery特效插件汇总
2014/12/07 Javascript
JavaScript中的console.log()函数详细介绍
2014/12/29 Javascript
Nodejs学习笔记之Global Objects全局对象
2015/01/13 NodeJs
jQuery删除一个元素后淡出效果展示删除过程的方法
2015/03/18 Javascript
javascript动态生成树形菜单的方法
2015/11/14 Javascript
JavaScript中定义类的方式详解
2016/01/07 Javascript
js获取当前日期时间及其它日期操作汇总
2016/03/08 Javascript
Jquery中attr与prop的区别详解
2017/05/27 jQuery
javascript浏览器用户代理检测脚本实现方法
2017/10/27 Javascript
jquery实现回车键触发事件(实例讲解)
2017/11/21 jQuery
将Sublime Text 3 添加到右键中的简单方法
2017/12/12 Javascript
解决antd Form 表单校验方法无响应的问题
2020/10/27 Javascript
小结Python用fork来创建子进程注意事项
2014/07/03 Python
Python中非常实用的一些功能和函数分享
2015/02/14 Python
python多进程中的内存复制(实例讲解)
2018/01/05 Python
Selenium的使用详解
2018/10/19 Python
对python3 Serial 串口助手的接收读取数据方法详解
2019/06/12 Python
关于h5中的fetch方法解读(小结)
2017/11/15 HTML / CSS
美国保健品专家:Life Extension
2018/05/04 全球购物
《莫高窟》教学反思
2014/02/25 职场文书
交通志愿者活动总结
2014/06/27 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
2015年客房服务员工作总结
2015/05/15 职场文书
居住证明范文
2015/06/17 职场文书
Python制作表白爱心合集
2022/01/22 Python
正则表达式拆分url实例代码
2022/02/24 Java/Android