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代码
Mar 16 Javascript
toggle一个div显示或隐藏且可扩展成自定义下拉框
Sep 12 Javascript
jQuery实现防止提交按钮被双击的方法
Mar 24 Javascript
JavaScript中使用Math.floor()方法对数字取整
Jun 15 Javascript
jquery中ready()函数执行的时机和window的load事件比较
Jun 22 Javascript
jQuery中$.ajax()和$.getJson()同步处理详解
Aug 12 Javascript
js编写的treeview使用方法
Nov 11 Javascript
利用Query+bootstrap和js两种方式实现日期选择器
Jan 10 Javascript
jQuery插件HighCharts绘制2D柱状图、折线图和饼图的组合图效果示例【附demo源码下载】
Mar 09 Javascript
鼠标拖动改变DIV等网页元素的大小的实现方法
Jul 06 Javascript
js实现批量删除功能
Aug 27 Javascript
javascript实现智能手环时间显示
Sep 18 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系列学习之日期函数使用介绍
2012/08/18 PHP
解析PHP中一些可能会被忽略的问题
2013/06/21 PHP
php中file_get_content 和curl以及fopen 效率分析
2014/09/19 PHP
thinkphp普通查询与表达式查询实例分析
2014/11/24 PHP
ucenter通信原理分析
2015/01/09 PHP
Yii学习总结之数据访问对象 (DAO)
2015/02/22 PHP
php通过array_merge()函数合并关联和非关联数组的方法
2015/03/18 PHP
PHP分享图片的生成方法
2018/04/25 PHP
基于逻辑运算的简单权限系统(实现) JS 版
2007/03/24 Javascript
asp.net+jquery滚动滚动条加载数据的下拉控件
2010/06/25 Javascript
了不起的node.js读书笔记之node.js中的特性
2014/12/22 Javascript
JavaScript语言对Unicode字符集的支持详解
2014/12/30 Javascript
JAVA四种基本排序方法实例总结
2015/07/24 Javascript
javascript for-in有序遍历json数据并探讨各个浏览器差异
2015/11/30 Javascript
JavaSctit 利用FileReader和滤镜上传图片预览功能
2017/09/05 Javascript
Thinkphp5微信小程序获取用户信息接口的实例详解
2017/09/26 Javascript
js统计页面上每个标签的数量实例代码
2018/05/29 Javascript
编写v-for循环的技巧汇总
2020/12/01 Javascript
python中os模块详解
2016/10/14 Python
Python调用微信公众平台接口操作示例
2017/07/08 Python
Python 实现简单的shell sed替换功能(实例讲解)
2017/09/29 Python
Python3爬虫学习之应对网站反爬虫机制的方法分析
2018/12/12 Python
python中元组的用法整理
2020/06/15 Python
学python需要去培训机构吗
2020/07/01 Python
python中remove函数的踩坑记录
2021/01/04 Python
static函数与普通函数有什么区别
2015/12/25 面试题
新品发布会主持词
2014/04/02 职场文书
计生专干事迹
2014/05/28 职场文书
电子商务实训报告总结
2014/11/05 职场文书
交通事故死亡赔偿协议书
2014/12/03 职场文书
2014年语文教学工作总结
2014/12/17 职场文书
金秋助学感谢信
2015/01/21 职场文书
投标邀请书范本
2015/02/02 职场文书
2016年小学生寒假家长评语
2015/10/10 职场文书
2019最新企业员工考勤管理制度(通用版)!
2019/07/02 职场文书
python保存图片的四个常用方法
2022/02/28 Python