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 相关文章推荐
javascript vvorld 在线加密破解方法
Nov 13 Javascript
Prototype源码浅析 Enumerable部分之each方法
Jan 16 Javascript
使用JavaScript判断手机浏览器是横屏还是竖屏问题
Aug 02 Javascript
基于d3.js实现实时刷新的折线图
Aug 03 Javascript
JavaScript九九乘法口诀表的简单实现
Oct 04 Javascript
浅谈angularjs中响应回车事件
Apr 24 Javascript
JavaScript 获取元素在父节点中的下标(推荐)
Jun 28 Javascript
JavaScript函数中的this四种绑定形式
Aug 15 Javascript
JS改变页面颜色源码分享
Feb 24 Javascript
jQuery实现表单动态添加数据并提交的方法
Jul 19 jQuery
浅谈vue同一页面中拥有两个表单时,的验证问题
Sep 18 Javascript
layui 富文本图片上传接口与普通按钮 文件上传接口的例子
Sep 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
PHP性能优化 产生高度优化代码
2011/07/22 PHP
php将图片保存为不同尺寸图片的图片类实例
2015/03/30 PHP
php判断用户是否关注微信公众号
2016/07/22 PHP
通过修改Laravel Auth使用salt和password进行认证用户详解
2017/08/17 PHP
PHP实现的ID混淆算法类与用法示例
2018/08/10 PHP
JavaScript 节点操作 以及DOMDocument属性和方法
2007/12/06 Javascript
浅谈Javascript事件处理程序的几种方式
2012/06/27 Javascript
原生js实现shift/ctrl/alt按键的获取
2013/04/08 Javascript
Jquery 实现checkbox全选方法
2015/01/28 Javascript
javascript事件模型实例分析
2015/01/30 Javascript
深入理解JavaScript系列(18):面向对象编程之ECMAScript实现
2015/03/05 Javascript
js显示文本框提示文字的方法
2015/05/07 Javascript
js简单工厂模式用法实例
2015/06/30 Javascript
jquery实现表单验证简单实例演示
2015/11/23 Javascript
JQuery ztree带筛选、异步加载实例讲解
2016/02/25 Javascript
javascript实现瀑布流动态加载图片原理
2016/08/12 Javascript
详解angularjs popup-table 弹出框表格指令
2017/09/20 Javascript
Angular表格神器ui-grid应用详解
2017/09/29 Javascript
VUE2.0+Element-UI+Echarts封装的组件实例
2018/03/02 Javascript
Bootstrap模态对话框用法简单示例
2018/08/31 Javascript
怎么使用javascript深度拷贝一个数组
2019/06/06 Javascript
React组件对子组件children进行加强的方法
2019/06/23 Javascript
python+mysql实现简单的web程序
2014/09/11 Python
Python中itertools模块用法详解
2014/09/25 Python
详解Python的迭代器、生成器以及相关的itertools包
2015/04/02 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
Python字符串格式化常用手段及注意事项
2020/06/17 Python
使用索引有什么好处
2016/07/27 面试题
数控个人求职信范文
2014/02/03 职场文书
小学信息技术教学反思
2014/02/10 职场文书
开展创先争优活动总结
2014/08/28 职场文书
国家助学金感谢信
2015/01/21 职场文书
医院办公室主任岗位职责
2015/04/01 职场文书
2015年检验员工作总结范文
2015/04/30 职场文书
社区安全温馨提示语
2015/07/14 职场文书
用 Python 定义 Schema 并生成 Parquet 文件详情
2021/09/25 Python