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 相关文章推荐
ImageFlow可鼠标控制图片滚动
Jan 30 Javascript
javascript 窗口加载蒙板 内嵌网页内容
Nov 19 Javascript
jQuery 源码分析笔记(5) jQuery.support
Jun 19 Javascript
js时间比较示例分享(日期比较)
Mar 05 Javascript
禁止iframe脚本弹出的窗口覆盖了父窗口的方法
Sep 06 Javascript
在linux中使用包管理器安装node.js
Mar 13 Javascript
JS处理json日期格式化问题
Oct 01 Javascript
javascript新闻跑马灯实例代码
Jul 29 Javascript
javascript仿京东导航左侧分类导航下拉菜单效果
Nov 25 Javascript
详解AngularJS中的表单验证(推荐)
Nov 17 Javascript
jQuery基于随机数解决中午吃什么去哪吃问题示例
Dec 29 jQuery
js动态获取时间的方法分析
Aug 02 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 获取客户端的真实ip
2009/11/30 PHP
使用PHP实现密保卡功能实现代码<打包下载直接运行>
2011/10/09 PHP
php中将数组存到文件里的实现代码
2012/01/19 PHP
php实现简单加入购物车功能
2017/03/07 PHP
php实现自定义中奖项数和概率的抽奖函数示例
2017/05/26 PHP
神奇的代码 通杀各种网站-可随意修改复制页面内容
2008/07/17 Javascript
js Event对象的5种坐标
2011/09/12 Javascript
javascript定时变换图片实例代码
2013/03/17 Javascript
jquery文字上下滚动的实现方法
2013/03/22 Javascript
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
javascript类型系统 Array对象学习笔记
2016/01/09 Javascript
详解angular2实现ng2-router 路由和嵌套路由
2017/03/24 Javascript
JavaScript中错误正确处理方式小结你用对了吗
2017/10/10 Javascript
vue路由嵌套的SPA实现步骤
2017/11/06 Javascript
基于vue-element组件实现音乐播放器功能
2018/05/06 Javascript
Django+vue跨域问题解决的详细步骤
2019/01/20 Javascript
angular异步验证防抖踩坑实录
2019/12/01 Javascript
vue仿淘宝滑动验证码功能(样式模仿)
2019/12/10 Javascript
继承行为在 ES5 与 ES6 中的区别详解
2019/12/24 Javascript
基于python编写的微博应用
2014/10/17 Python
Python使用POP3和SMTP协议收发邮件的示例代码
2019/04/16 Python
利用python list完成最简单的DB连接池方法
2019/08/09 Python
Python基于Dlib的人脸识别系统的实现
2020/02/26 Python
利用Python如何实时检测自身内存占用
2020/05/09 Python
python3实现简单飞机大战
2020/11/29 Python
一款纯css3实现的响应式导航
2014/10/31 HTML / CSS
浅析rem和em和px vh vw和% 移动端长度单位
2016/04/28 HTML / CSS
美国独家设计师眼镜在线光学商店:Glasses Gallery
2017/12/28 全球购物
公司人力资源的自我评价
2014/01/02 职场文书
住房公积金接收函
2014/01/09 职场文书
施工安全承诺书
2014/05/22 职场文书
工程学毕业生自荐信
2014/06/14 职场文书
个人事迹材料怎么写
2014/12/30 职场文书
详解MySQL数据库千万级数据查询和存储
2021/05/18 MySQL
使用CSS连接数据库的方式
2022/02/28 HTML / CSS
DSP接收机前端设想
2022/04/05 无线电