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实多级联动下拉菜单类,简单实现省市区联动菜单!
May 03 Javascript
使用JQuery进行跨域请求
Jan 25 Javascript
JS 文件大小判断的实现代码
Apr 07 Javascript
Jquery实现带动画效果的经典二级导航菜单
Mar 22 Javascript
JavaScript支持的最大递归调用次数分析
Jun 24 Javascript
node.js超时timeout详解
Nov 26 Javascript
微信小程序 两种为对象属性赋值的方式详解
Feb 23 Javascript
VUE实现表单元素双向绑定(总结)
Aug 08 Javascript
Angular实现的日程表功能【可添加及隐藏显示内容】
Dec 27 Javascript
使用Node.js在深度学习中做图片预处理的方法
Sep 18 Javascript
javascript实现移动端红包雨页面
Jun 23 Javascript
JavaScript实现复选框全选和取消全选
Nov 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
PHP form 表单传参明细研究
2009/07/17 PHP
PHP通过header实现文本文件下载的代码
2010/08/08 PHP
ThinkPHP模板判断输出Present标签用法详解
2014/06/30 PHP
使用Appcan客户端自动更新PHP版本号(全)
2015/07/31 PHP
yii2.0框架使用 beforeAction 防非法登陆的方法分析
2019/09/11 PHP
JQuery1.4+ Ajax IE8 内存泄漏问题
2010/10/15 Javascript
基于jQuery的投票系统显示结果插件
2011/08/12 Javascript
chrome浏览器不支持onmouseleave事件的解决技巧
2013/05/31 Javascript
js限制input标签中只能输入中文
2015/06/26 Javascript
更高效的使用JQuery 这里总结了8个小技巧
2016/04/13 Javascript
confirm确认对话框的实现方法总结
2016/06/17 Javascript
js操作XML文件的实现方法兼容IE与FireFox
2016/06/25 Javascript
基于Javascript实现的不重复ID的生成器
2016/12/25 Javascript
webuploader模态框ueditor显示问题解决方法
2016/12/27 Javascript
js简易版购物车功能
2017/06/17 Javascript
ReactNative中使用Redux架构总结
2017/12/15 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
jQuery实现飞机大战小游戏
2020/07/05 jQuery
[55:03]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第二场 11.20
2020/11/20 DOTA
Python基于正则表达式实现文件内容替换的方法
2017/08/30 Python
PyQt5每天必学之组合框
2018/04/20 Python
Python中三元表达式的几种写法介绍
2019/03/04 Python
python并发爬虫实用工具tomorrow实用解析
2019/09/25 Python
python实现图片二值化及灰度处理方式
2019/12/07 Python
Python装饰器结合递归原理解析
2020/07/02 Python
Pandas的Apply函数具体使用
2020/07/21 Python
Pycharm Git 设置方法
2020/09/15 Python
Pam & Gela官网:美国性感前卫女装品牌
2018/07/19 全球购物
意大利奢侈品零售商:ilDuomo Novara
2019/09/11 全球购物
车间主管岗位职责
2013/11/14 职场文书
学生打架检讨书大全
2014/01/23 职场文书
警察先进个人事迹材料
2014/05/16 职场文书
民事答辩状格式范文
2015/05/21 职场文书
什么是检讨书?检讨书的格式及范文
2019/11/05 职场文书
Python使用OpenCV实现虚拟缩放效果
2022/02/28 Python
SQL Server中锁的用法
2022/05/20 SQL Server