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 相关文章推荐
几个高效,简洁的字符处理函数
Apr 12 Javascript
ExtJS 简介 让你知道extjs是什么
Dec 29 Javascript
通用javascript脚本函数库 方便开发
Oct 13 Javascript
Javascript UrlDecode函数代码
Jan 09 Javascript
js判断输入是否为正整数、浮点数等数字的函数代码
Nov 17 Javascript
javascript实现回车键提交表单方法总结
Jan 10 Javascript
jQuery动态添加
Apr 07 Javascript
教你JS中的运算符乘方、开方及变量格式转换
Aug 09 Javascript
angular.extend方法的具体使用
Sep 14 Javascript
JS实现在线ps功能详解
Jul 31 Javascript
JS数组方法reverse()用法实例分析
Jan 18 Javascript
使用Vue 自定义文件选择器组件的实例代码
Mar 04 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 更新数据库中断的解决方法
2009/06/05 PHP
PHP在线调试执行的实现方法(附demo源码)
2016/04/28 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
PHP7中I/O模型内核剖析详解
2019/04/14 PHP
Js+XML 操作
2006/09/20 Javascript
JS判断移动端访问设备并加载对应CSS样式
2014/06/13 Javascript
javascript event在FF和IE的兼容传参心得(绝对好用)
2014/07/10 Javascript
jQuery中:header选择器用法实例
2014/12/29 Javascript
jquery性能优化高级技巧
2015/08/24 Javascript
jquery实现仿Flash的横向滑动菜单效果代码
2015/09/17 Javascript
js实现简单的验证码
2015/12/25 Javascript
JavaScript页面实时显示当前时间实例代码
2016/10/23 Javascript
微信小程序 数组中的push与concat的区别
2017/01/05 Javascript
原生JS实现移动端web轮播图详解(结合Tween算法造轮子)
2017/09/10 Javascript
详解用vue2.x版本+adminLTE开源框架搭建后台应用模版
2019/03/15 Javascript
JavaScript的级联函数用法简单示例【链式调用】
2019/03/26 Javascript
JavaScript中AOP的实现与应用
2019/05/06 Javascript
vue-cli3中配置alias和打包加hash值操作
2020/09/04 Javascript
详解Vue的七种传值方式
2021/02/08 Vue.js
[01:11]steam端dota2实名认证操作流程视频
2021/03/11 DOTA
深入浅析python继承问题
2016/05/29 Python
Python制作钉钉加密/解密工具
2016/12/07 Python
python实现将range()函数生成的数字存储在一个列表中
2020/04/02 Python
python中re模块知识点总结
2021/01/17 Python
使用css3和jquery实现可伸缩搜索框
2014/02/12 HTML / CSS
HTML5图片层叠的实现示例
2020/07/07 HTML / CSS
火山咖啡:Volcanica Coffee
2019/10/29 全球购物
什么是Web Service?
2012/07/25 面试题
升职自荐信
2013/11/28 职场文书
数学高效课堂实施方案
2014/03/29 职场文书
《卖木雕的少年》教学反思
2014/04/11 职场文书
篮球比赛拉拉队口号
2014/06/10 职场文书
关于成绩下滑的自我检讨书
2014/09/20 职场文书
辩护词范文大全
2015/05/21 职场文书
大学生军训感言
2015/08/01 职场文书
html实现随机点名器的示例代码
2021/04/02 Javascript