ES6笔记 之 基本数据类型 Symbol

Symbol是ES6(ECMA Script 2015)标准中定义的基本(原始)数据类型(primitive type)。
跟Number、String、Boolean、Undefined、Null 可以组成六兄弟。

很多前端面试题会问及JS基本数据类型的问题。这并不需要死记硬背。下面做一些简单的回顾:
– 基本类型值是数据段,可以操作保存在变量中的实际值。
– 基本类型的值在内存中占据固定大小的空间,被保存在栈内存中。
– 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本。
– 基本类型不能添加属性。

以上描述,反映了基本数据类型的最大特点:immutable(不可变性)

OK,基于这些特点,来说一下Symbol。

Symbol是一种标识。

// 创建symbol
let sym = Symbol();
let sym1 = Symbol("foo");
let sym2 = Symbol("foo");

typeof sym //结果 symbol
sym //输出sym结果:Symbol()
sym1 === sym2  //结果:false

构建一个Symbol类型数据很简单,类似 Number(‘1.1’)、String(’123’)

但是Symbol不支持包装器对象的访问(Wrapper),通俗讲就是无法使用 new Symbol(“foo”)这样的构造方法。

对于包装器生成的对象,有如下特点:

let str = new String("hello-world");
typeof str  //输出:object
str.valueOf() //输出:"hello-world"
str  = str + "!" //输出:"hello-world!"
new String("123") === new String("123") //输出:false

str是一个字符型对象,其属性包含字面值,并且通过运算符操作可以进行类型转换后的值运算。
ES6语法中,理论上应让基础类型无法使用包装器对象。但String、Number、Boolean 保留了在上个版本的标准可使用new来构建的冗余特性。

以上是对Symbol构建的一些补充。

Symbol的另一个重要特性:独特性(唯一性)

以上一些例子看出,即使从相同的字面值创建出来的Symbol,也不代表相同。

Symbol的机理

从Symbol类来看,它提供一些静态方法来访问 JavaScript 全局 symbol 表,Symbol.for()和 Symbol.keyFor(),还有一些静态属性用来保存已存在通用对象里的特定 symbol 地址。
所以,Symbol是存在于整个运行时环境中的,其注册信息存在于JavaScript编译器中。Symbol.for(“tokenString”) 方法从注册表返回一个 symbol 值,Symbol.keyFor(symbolValue) 方法从注册表返回 token 字符串。

var propName = Symbol();
Symbol.keyFor(Symbol.for("propName"))=="propName";  // true

Symbol的用武之地 ———— 创建匿名的“对象属性”

var propName = Symbol();
this[propName] = function() {};
this.propName()  //报错:propName不是函数

以上貌似是对this对象进行了动态属性添加,但访问属性时并没有找到,所以以上propName是匿名的,或者说是不可能被访问到的。

那么如果找不到又有何用呢?
事实上可以用Object.getOwnPropertySymbols(this)返回数组包含所有的symbol

this[Object.getOwnPropertySymbols(this)[0]]  //返回上面定义的匿名函数

进一步来看,用Symbol来实现私有属性是再理想不过的了。

(function() {
    var key = Symbol("private-prop");

    function MyClass(privateData) {
      this[key] = privateData;
    }

    MyClass.prototype = {
      func: function() {
        return "data: " + this[key];
      }
    };

    var c = new MyClass("private data")
    console.log(key);
    console.log(c["key"]);
    console.log(c.func());

})();

// Output:
// undefined
// undefined
// data: private data

参考

MDN-Primitive
变量存储
MDN-JS数据类型
MSDN-Symbol

发表评论

电子邮件地址不会被公开。 必填项已用*标注