ES5 模拟 ES6 的 Symbol 实现私有成员功能示例

本文实例讲述了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.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • JavaScript 面向对象的之私有成员和公开成员

    上两节讲了 JavaScript 面向对象之命名空间 与 javascript 面向对象的JavaScript类,大家可以先看上面的再继续往下看. 其实很简单,废话少说,看了下面的代码及注释相信你就会一目了然! 复制代码 代码如下: //声明类,就是一个方法,其实在JavaScript中,命名空间.类.成员.... 一切皆对象 MyClass =function(){ var _this=this; //私有变量 var aa="11"; //公开变量 this.bb="22

  • ES6概念 Symbol toString()方法

    Symbol toString()方法: 此方法会返回当前symbol对象的字符串表示. 更多关于Symbol的内容可以参阅ES2015 Symbol一章节. 语法结构: symbol.toString(); 代码实例: let s = Symbol("我们"); console.log(s+"欢迎您"); Symbol值不能够隐式转换为字符串类型. let s = Symbol("我们"); console.log(s.toString());

  • Javascript类定义语法,私有成员、受保护成员、静态成员等介绍

    其实通俗的讲类就是对象的模板,为了增强JS的OO特性,受mootoos框架启发我们可以使用一个JSON对象来描述这个对象的模板.在这个模板中我们可以模拟实现私有成员,受保护成员,静态成员. 这是一个在JS中模拟的类定义语法,代码中Class是一个自定义函数,它接受两个参数,第一个参数是类名.第二个参数是一个JSON用来一个对象的模板.在这个JSON对象中其中字段 "extend",,"initialize","static" 为一些预定义关键字,

  • Javascript ES6中数据类型Symbol的使用详解

    介绍 Symbol 是一种特殊的.不可变的数据类型,可以作为对象属性的标识符使用,表示独一无二的值.Symbol 对象是一个 symbol primitive data type 的隐式对象包装器. 它是JavaScript语言的第七种数据类型,前6种分别是:Undefined.Null.Boolean.String.Number.Object. 语法 Symbol([description]) Parameters description : 可选的字符串.可用于调试但不访问符号本身的符号的说

  • ES6中Symbol类型用法实例详解

    本文实例讲述了ES6中的Symbol类型.分享给大家供大家参考,具体如下: Symbol是在ES6中新加入的类型. 正如我们所知,JavaScript中有以下几种类型: Undefined ,Null ,Boolean ,Number ,String, Object. 但是上述类型在处理某些情况的时候是远远不够的.下面我们来举一个例子: 假设我们要移动div,也需要在某些情况下判断该div是否处于移动状态,所以我们会想到给div这类的对象设置一个属性. if (element.isMoving)

  • ES6中Symbol、Set和Map用法详解

    本文实例讲述了ES6中Symbol.Set和Map用法.分享给大家供大家参考,具体如下: Symbol 1.Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值.它是 JavaScript 语言的第七种数据类型,前六种分别是:undefined.null.布尔值(Boolean).字符串(String).数值(Number).对象(Object): 2.Symbol 值通过Symbol函数生成,可以作为对象的属性名使用,保证不会与其他属性名产生冲突: let s = Symbo

  • ES6新特性之Symbol类型用法分析

    本文实例讲述了ES6新特性之Symbol类型用法.分享给大家供大家参考,具体如下: Symbol类型 1. 为了避免属性名的冲突,ES6新增了Symbol类型.Symbol可以产生一个独一无二的值. let s1 = Symbol('a'); let s2 = Symbol('a'); console.log(s1); //Symbol(a) console.log(typeof s1); //symbol console.log(s1 == s2); //false 2.Symbol用于属性名

  • ES6 Symbol数据类型的应用实例分析

    本文实例讲述了ES6 Symbol数据类型的应用.分享给大家供大家参考,具体如下: Symbol,是ES6中引入的新的数据类型,表示独一无二的值.在面向对象中,每个对象都有字符串类型的属性,新方法的名字就有可能与现有方法产生冲突.Symbol的引入保证每个属性的名字都是独一无二的,这样就从根本上防止属性名的冲突. ES6之前对象属性的命名方法 var obj = { name:'Joh', 'my name': 'Johnny' } console.log(obj.name); // Joh c

  • es6 symbol的实现方法示例

    背景 ES5 的对象属性名都是字符串,这容易造成属性名的冲突.比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突.如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突.这就是 ES6 引入Symbol的原因. ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值.它是 JavaScript 语言的第七种数据类型,前六种是:undefined.null.布尔值(Boolean).字

  • ES6概念 Symbol.keyFor()方法

    Symbol.keyFor()方法: 此方法会获取对应Symbol值的键. 更多关于Symbol内容可以参阅ES2015 Symbol一章节. 语法结构: Symbol.keyFor(sym); 参数解析: (1).sym:必需,要获取键值的Symbol值. 代码实例: let s = Symbol.for("我们"); console.log(Symbol.keyFor(s)); 上面的代码可以获取指定Symbol值的键. let s = Symbol("我们")

  • 详解ES6 Symbol 的用途

    Symbol 唯一的用途就是标识对象属性,表明对象支持的功能. 相比于字符属性名,Symbol 的区别在于唯一,可避免名字冲突. 这样 Symbol 就给出了唯一标识类型信息的一种方式,从这个角度看有点类似 C++ 的 Traits. 解决了什么问题 在 JavaScript 中要判断一个对象支持的功能,常常需要做一些 Duck Test. 比如经常需要判断一个对象是否可以按照数组的方式去迭代,这类对象称为 Array-like. lodash 中是这样判断的: function isArray

  • JavaScript 私有成员分析

    对象 JavaScript操作都是关于对象的.数组(Array)是对象,函数(Function)是对象.Object(类型)是对象.那么什么是对象呢?对象就是"名称-值"对(name-value).名称是字符串,值可以是字符串.数值.布尔值或对象(包括数组和函数).对象经常用哈希表实现,所以取值速度很快. 如果对象的一个值是函数(function),我们可以认为它是成员函数,当成员函数被调用时,this变量就会指向该对象.成员函数可以通过this变量访问对象的成员. 对象可以通过构造器

随机推荐