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 相关文章推荐
用jquery设置按钮的disabled属性的实现代码
Nov 28 Javascript
jquery中交替点击事件的实现代码
Feb 14 Javascript
IE中JS跳转丢失referrer问题的2个解决方法
Jul 18 Javascript
基于jQuery实现点击弹出层实例代码
Jan 01 Javascript
JS Array创建及concat()split()slice()的使用方法
Jun 03 Javascript
js与applet相互调用的方法
Jun 22 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
Jul 28 Javascript
JavaScript高级函数应用之分时函数实例分析
Aug 03 Javascript
Node.js原生api搭建web服务器的方法步骤
Feb 15 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
Apr 30 Javascript
Vue实现附件上传功能
May 28 Javascript
如何基于jQuery实现五角星评分
Sep 02 jQuery
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
xml在joomla表单中的应用详解分享
2012/07/19 PHP
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
2013/01/11 PHP
在Mac上编译安装PHP7的开发环境
2015/07/28 PHP
PHP实现SMTP邮件的发送实例
2018/09/27 PHP
xmlHTTP实例
2006/10/24 Javascript
jQuery循环滚动展示代码 可应用到文字和图片上
2012/05/11 Javascript
网站404页面3秒后跳到首页的实例代码
2013/08/16 Javascript
js 与 php 通过json数据进行通讯示例
2014/03/26 Javascript
js+html5实现canvas绘制简单矩形的方法
2015/06/05 Javascript
javascript验证手机号和实现星号(*)代替实例
2016/08/16 Javascript
JS匿名函数类生成方式实例分析
2016/11/26 Javascript
Angular的自定义指令以及实例
2016/12/26 Javascript
vue通过路由实现页面刷新的方法
2018/01/25 Javascript
微信小程序使用swiper组件实现层叠轮播图
2018/11/04 Javascript
JavaScript实现随机五位数验证码
2019/09/27 Javascript
如何利用JS将手机号中间四位变成*号
2020/09/29 Javascript
基于python编写的微博应用
2014/10/17 Python
Python实现程序的单一实例用法分析
2015/06/03 Python
在Python的一段程序中如何使用多次事件循环详解
2017/09/07 Python
Python之多线程爬虫抓取网页图片的示例代码
2018/01/10 Python
python2.7实现爬虫网页数据
2018/05/25 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
对numpy中数组转置的求解以及向量内积计算方法
2018/10/31 Python
通过cmd进入python的实例操作
2019/06/26 Python
python小程序之4名牌手洗牌发牌问题解析
2020/05/15 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
浅析Python模块之间的相互引用问题
2021/02/26 Python
Clarria化妆品官方网站:购买天然和有机化妆品系列
2018/04/08 全球购物
优秀毕业生的求职信
2014/07/21 职场文书
幼师辞职信怎么写
2015/02/27 职场文书
物流仓管员岗位职责
2015/04/01 职场文书
2015党建工作简报
2015/07/21 职场文书
毕业典礼致辞
2015/07/29 职场文书
高中16字霸气押韵班级口号集锦!
2019/06/27 职场文书
复制别人的成功真的会成功吗?
2019/10/17 职场文书
python中Pyqt5使用Qlabel标签播放视频
2022/04/22 Python