本文节选自Nicholas C. Zakas所著《Understanding EcmaScript6》的中文版《深入理解ES6》,由电子工业出版社出版。
著:【美】Nicholas C. Zakas(尼古拉斯·泽卡斯)
译:刘振涛
责编:陈秋歌,寻求报道或者投稿请发邮件至chenqg#csdn.net。

导读:本文节选自图书《深入理解ES6》第六章,Symbol为ECMAScript 6引入了第6种原始类型,本文将详解如何有效地使用它。

在ECMAScript 5及早期版本中,语言包含5种原始类型:字符串型、数字型、布尔型、null和undefined。ECMAScript 6引入了第6种原始类型:Symbol。起初,人们用它来创建对象的私有成员,JavaScript开发者们对这个新特性期待已久。在Symbol出现以前,人们一直通过属性名来访问所有属性,无论属性名由什么元素构成,全部通过一个字符串类型的名称来访问;私有名称原本是为了让开发者们创建非字符串属性名称而设计的,但是一般的技术无法检测这些属性的私有名称。

私有名称最终演变成了ECMAScript 6中的Symbol,本章将讲解如何有效地使用它。虽然通过Symbol可以为属性添加非字符串名称,但是其隐私性就被打破了。最终,新标准中将Symbol属性与对象中的其他属性分别分类。

创建Symbol

所有原始值,除了Symbol以外都有各自的字面形式,例如布尔类型的true或数字类型的42。可以通过全局的Symbol函数创建一个Symbol,就像这样:

letfirstName = Symbol();
let person = {};person[firstName] = "Nicholas";
console.log(person[firstName]); // "Nicholas"

在上面这段代码中,创建了一个名为firstName的Symbol,用它将一个新的属性赋值给person对象,每当你想访问这个属性时一定要用到最初定义的Symbol。记得要合理命名Symbol变量,这样可以轻松区分出它所指代的内容。

注意:由于Symbol是原始值,因此调用new Symbol()会导致程序抛出错误。也可以执行new Object(你的Symbol)创建一个Symbol的实例,但目前尚不清楚这个功能何时可以使用。

Symbol函数接受一个可选参数,其可以让你添加一段文本描述即将创建的Symbol,这段描述不可用于属性访问,但是建议你在每次创建Symbol时都添加这样一段描述,以便于阅读代码和调试Symbol程序。

let firstName = Symbol("first name");
let person = {};person[firstName] = "Nicholas";console.log("first name" in person); // false
console.log(person[firstName]); // "Nicholas"
console.log(firstName); // "Symbol(first name)"

Symbol的描述被存储在内部的[[Description]]属性中,只有当调用Symbol的toString()方法时才可以读取这个属性。在执行console.log()时隐式调用了firstName的toString()方法,所以它的描述会被打印到日志中,但不能直接在代码里访问[[Description]]。

Symbol的辨识方法

Symbol是原始值,且ECMAScript 6同时扩展了typeof操作符,支持返回”Symbol”,所以可以用typeof来检测变量是否为Symbol类型。

let symbol = Symbol("test symbol");
console.log(typeof symbol); // "symbol"

通过其他间接方式也可以检测变量是否为Symbol类型,但是typeof操作符是最准确也是你最应首选的检测方式。

Symbol的使用方法

所有使用可计算属性名的地方,都可以使用Symbol。前面我们看到的都是在括号中使用Symbol,事实上,Symbol也可以用于可计算对象字面量属性名、Object.defineProperty()方法和Object.defineProperties()方法的调用过程中。

letfirstName = Symbol("first name");// 使用一个可计算对象字面量属性
let person = {
[firstName]: "Nicholas"
};

// 将属性设置为只读
Object.defineProperty(person, firstName, { writable: false });

letlastName = Symbol("last name");

Object.defineProperties(person, {[lastName]: {value: "Zakas",
writable: false
}
});

console.log(person[firstName]); // "Nicholas"
console.log(person[lastName]); // "Zakas"

在此示例中,首先通过可计算对象字面量属性语法为person对象创建了一个Symbol属性firstName。后面一行代码将这个属性设置为只读。随后,通过Object.defineProperties()方法创建一个只读的Symbol属性lastName,此处再次使用了对象字面量属性,但却是作为Object.defineProperties()方法的第二个参数使用。

尽管在所有使用可计算属性名的地方,都可以使用Symbol来代替,但是为了在不同代码片段间有效地共享这些Symbol,需要建立一个体系。

Symbol共享体系

有时我们可能希望在不同的代码中共享同一个Symbol,例如,在你的应用中有两种不同的对象类型,但是你希望它们使用同一个Symbol属性来表示一个独特的标识符。一般而言,在很大的代码库中或跨文件追踪Symbol非常困难而且容易出错,出于这些原因,ECMAScript 6提供了一个可以随时访问的全局Symbol注册表。

如果想创建一个可共享的Symbol,要使用Symbol.for()方法。它只接受一个参数,也就是即将创建的Symbol的字符串标识符,这个参数同样也被用作Symbol的描述,就像这样:

letuid = Symbol.for("uid");
let object = {};object[uid] = "12345";console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"

Symbol.for()方法首先在全局Symbol注册表中搜索键为”uid”的Symbol是否存在,如果存在,直接返回已有的Symbol;否则,创建一个新的Symbol,并使用这个键在Symbol全局注册表中注册,随即返回新创建的Symbol。
后续如果再传入同样的键调用Symbol.for()会返回相同的Symbol,像这样:

letuid = Symbol.for("uid");
let object = {
[uid]: "12345"
};console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"let uid2 = Symbol.for("uid");console.log(uid === uid2); // true
console.log(object[uid2]); // "12345"
console.log(uid2); // "Symbol(uid)"

在这个示例中,uid和uid2包含相同的Symbol并且可以互换使用。第一次调用Symbol.for()方法创建这个Symbol,第二次调用可以直接从Symbol的全局注册表中检索到这个Symbol。

还有一个与Symbol共享有关的特性:可以使用Symbol.keyFor()方法在Symbol全局注册表中检索与Symbol有关的键。举个例子:

letuid = Symbol.for("uid");
console.log(Symbol.keyFor(uid)); // "uid"let uid2 = Symbol.for("uid");
console.log(Symbol.keyFor(uid2)); // "uid"let uid3 = Symbol("uid");
console.log(Symbol.keyFor(uid3)); // undefined

注意,uid和uid2都返回了”uid”这个键,而在Symbol全局注册表中不存在uid3这个Symbol,也就是不存在与之有关的键,所以最终返回undefined。

特别提醒:Symbol全局注册表是一个类似全局作用域的共享环境,也就是说你不能假设目前环境中存在哪些键。当使用第三方组件时,尽量使用Symbol键的命名空间以减少命名冲突。举个例子,jQuery的代码可以为所有键添加”jquery”前缀,就像”jquery.element”或其他类似的键。

点击订购:深入理解ES6


欢迎加入“CSDN前端开发者”群,与更多专家、技术同行进行热点、难点技术交流。请扫描以下二维码申请入群。

JavaScript大师Nicholas C. Zakas又一大作出中文版了相关推荐

  1. 世界级javascript大师们的视频与PPT

    来源:css9.net 导读:本文中的javascript大师们大多来自yahoo公司,可能说起他们的名字国内熟悉的人并不多,不过说到他们的作品那就几乎都认识,比如Jquery作者,<JavaS ...

  2. Nicholas C. Zakas:我热爱互联网技术的种种异端

    尼古拉斯·泽卡斯(Nicholas C. Zakas)是前端咨询师.畅销书作者.技术布道者,世界顶级 Web技术专家,曾在雅虎工作近5年,离开该公司前负责 My Yahoo! 和雅虎首页等大访问量站点 ...

  3. JavaScript大师必须掌握的12个知识点

    2019独角兽企业重金招聘Python工程师标准>>> 译者按: 前端技术涉及的越来越多! 原文: 10 things to learn on the way to becoming ...

  4. JavaScript大师必须掌握的12个知识点 1

    译者按: 前端技术涉及的越来越多! 原文: 10 things to learn on the way to becoming a JavaScript Master 译者: Fundebug 为了保 ...

  5. Nicholas C. Zakas如何面试前端工程师

    不要以为做前端很容易,已经做了前端的就不要理会别人说的"做网站的"!从下面这篇文章里面,我们也可以学到自身的不足,不然很有可能下个面试你的人就出了这样的题目. 面试前端工程师对我来 ...

  6. 草图大师三维建模工具SketchUp Pro 2023 中文版下载

    SketchUp Pro是一款功能强大的三维建模软件,它能够帮助用户快速地创建.修改和共享3D模型.该软件具有直观的界面和易于使用的工具,使用户可以轻松地进行模型设计.渲染和动画制作.同时,Sketc ...

  7. 《编写可维护的JavaScript》——1.7 直接量

    本节书摘来自异步社区<编写可维护的JavaScript>一书中的第1章,第1.7节,作者: [美]Nicholas C. Zakas 译者: 李晶 , 郭凯 , 张散集 更多章节内容可以访 ...

  8. JavaScript实现私有属性

    JavaScript实现私有属性 原文:JavaScript实现私有属性 JavaScript被很多人认为并不是一种面向对象语言,原因有很多种,比如JavaScript没有类,不能提供传统的类式继承: ...

  9. JSON与JavaScript的转换

    JSON是一种数据格式,可以把 JSON 直接传给 eval(),而且不必创建 DOM 对象.它有三种类型的值: 简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串.数 ...

  10. JavaScript高级程序设计-读书笔记(6)

    第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l        简单值:使用与JavaScript相同的语法,可以在JS ...

最新文章

  1. 递归思想解决输出目录下的全部文件
  2. Scala中val, lazy, def的区别
  3. Docker 容器技术 — Overview
  4. c语言中的字符变量用什么保留字来说明,第1、2章C语言基础练习题
  5. CentOS7,linux下nginx的安装过程——2.配置user,路径,openssl,make install,关闭防火墙,测试——源码
  6. 修改Eclipse自动换行长度
  7. java程序的调试过程
  8. 给你多少钱,你才会愿意为国家生孩子?
  9. Chrome在302重定向的时候对原请求产生2次请求的问题说明
  10. 以太坊可更新智能合约研究与开发综述
  11. MyBatis框架(6)动态sql
  12. linux初级:用useradd SB2,来建立新账户时,显示 bash:useradd:command not found的解决方法
  13. BDTC2016: 中航信 昆仑数据 兮易控股 宝信议题公布
  14. 将JPG图片直接转换成PDF软件操作步骤
  15. 互联网创业公司的经理​其实最主要是一个产品​经理
  16. 万测试验机软件,万测关注检查井盖质量检测
  17. 地球形状与重力场模型
  18. Sybase ASE 查询当前版本和所有数据库
  19. 台式计算机开关电源的电压规格,台式计算机ATX开关电源检修技巧
  20. Arduino门禁控制

热门文章

  1. 上门洗车APP开发的功能
  2. linux sdcc stc12c5a60s2,STC12C5A60S2单片机最小系统板20个参考例程分享
  3. Android全面解析之Window机制
  4. DSPE-PEG-TPP;磷脂-聚乙二醇-磷酸三苯酯;(阻燃剂TPP)是种含磷元素的化合物,可用作无卤环保型阻燃剂
  5. IEEE论文检测的字体未嵌入问题Times New Roman,Bold, Times New Roman,Italic is not embedded解决方法
  6. Spring Boot学习笔记(二十一)Spring boot 数据校验 @Validated、@Valid用法详解
  7. Processing基础
  8. 怎么在字符串中加加号python_python加号连接字符串
  9. javaEE 后台框架 SpringMVC Mybatis Shiro druid
  10. 渗透之——Win10完美去除桌面快捷图标小箭头