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 图像裁剪插件Jcrop的简单使用
May 22 Javascript
JSONP 跨域访问代理API-yahooapis实现代码
Dec 02 Javascript
JS与C#编码解码
Dec 03 Javascript
JavaScript中的原型链prototype介绍
Dec 30 Javascript
DOM基础教程之模型中的模型节点
Jan 19 Javascript
微信小程序 loading(加载中提示框)实例
Oct 28 Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
Feb 06 Javascript
js实现一键复制功能
Mar 16 Javascript
vue学习笔记之指令v-text && v-html && v-bind详解
May 12 Javascript
JS判断时间段的实现代码
Jun 14 Javascript
JS为什么说async/await是generator的语法糖详解
Jul 11 Javascript
html-webpack-plugin修改页面的title的方法
Jun 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使用正则表达式提取字符串中尖括号、小括号、中括号、大括号中的字符串
2020/04/05 PHP
基础的WordPress插件制作教程
2015/11/24 PHP
thinkphp中U方法按路由规则生成url的方法
2018/03/12 PHP
php求斐波那契数的两种实现方式【递归与递推】
2019/09/09 PHP
可缩放Reloaded-一个针对可缩放元素的复用组件
2007/03/10 Javascript
Jquery替换已存在于element上的event的方法
2010/03/09 Javascript
Jquery刷新页面背景图片随机变换的实现方法
2013/03/15 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
2015/10/14 Javascript
详解Bootstrap按钮
2016/01/04 Javascript
js复制内容到剪贴板代码,js复制代码的简单实例
2016/10/27 Javascript
JS中substring与substr的用法
2016/11/16 Javascript
Javascript 闭包详解及实例代码
2016/11/30 Javascript
JS表单数据验证的正则表达式(常用)
2017/02/18 Javascript
JavaScript学习笔记之函数记忆
2017/09/06 Javascript
javascript 产生随机数的几种方法总结
2017/09/26 Javascript
基于bootstrap写的一点localStorage本地储存
2017/11/21 Javascript
Node.js Buffer用法解读
2018/05/18 Javascript
Vue + Elementui实现多标签页共存的方法
2019/06/12 Javascript
python解析json实例方法
2013/11/19 Python
Python socket实现简单聊天室
2018/04/01 Python
python验证码识别教程之滑动验证码
2018/06/04 Python
Python安装与卸载流程详细步骤(图解)
2020/02/20 Python
html5中的input新属性range使用记录
2014/09/05 HTML / CSS
瑞典最大的儿童用品网上商店:pinkorblue.se
2021/03/09 全球购物
某公司.Net方向面试题
2014/04/24 面试题
建筑工程专业学生的自我评价
2013/12/25 职场文书
宿舍使用违章电器检讨书
2014/01/12 职场文书
美术教师自我鉴定
2014/02/12 职场文书
初三学生评语大全
2014/04/24 职场文书
高一课前三分钟演讲稿
2014/09/13 职场文书
教学改革问题查摆整改措施
2014/09/27 职场文书
2014年组织委员工作总结
2014/12/01 职场文书
2015应届毕业生自荐信范文
2015/03/05 职场文书
婚宴致辞
2015/07/28 职场文书
关于艺术节的开幕致辞
2016/03/04 职场文书
python使用pygame创建精灵Sprite
2021/04/06 Python