JavaScript学习之ES6 ES2015学记笔记(七)-标志(Symbols)

本文深入探讨了JavaScript中Symbol类型的特性及其应用场景,包括避免命名冲突、增强对象属性的安全性,以及在ES6规范中如何利用Symbol扩展instanceof操作符、防止新特性与旧代码冲突、支持新的字符串匹配类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Symbols是什么了?它是JavaScript中的第七种原始类型

JavaScript原始类型(值类型):String、Null、Undefined、Number、Boolean+Symblos

引用数据类型:Object,Array,Function

布尔类型只有两个值, true和 false,不会再创造第三种布尔值;数字类型和字符串类型的值更多,标准指明一共
有 18,437,736,874,454,810,627 种不同的数字(包括 NaN, 亦即“Not a Number”的缩写,代表非数字),可能存在的字符串类型的值拥有无以匹敌的数量,大约是(2144,115,188,075,855,872 - 1) ÷ 65,535 种、可能得出了一个错误的答案,但字符串类型值的集合一定是有限的,对象类型值的集合是无限的。

从一个简单的布尔类型出发

      当需要把别人外部函数存储到一个JavaScript对象中,例如判断CSS样式是否移动:创建一个标记

if (element.isMoving) {
    smoothAnimations(element);
}
element.isMoving = true;

这样也会有一些潜在的问题,事实上,上述代码很可能不是唯一一段操作 DOM 的代码。
可能会自定名称,比如:

if
(element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMovi
ng__) {
smoothAnimations(element);
}
element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMovin
g__ = true;

但是易读性太低,或者用密码学创建一个唯一的属性名称:

// 获取 1024 个 Unicode 字符的无意义命
var isMoving = SecureRandom.genera
...
if (element[isMoving]) {
    smoothAnimations(element);
}
element[isMoving] = true;

object[name]代码几乎不可能冲突,但是调试的时候会输出一长串乱序字符串。如何解决这个问题了?

symbol 是最终的解决方案
 

symbol 是程序创建并且可以用作属性键的值,并且它能避免命名冲突的风险

var nativeSymbol =Symbol();  //nativeSymbol的值与其他值不等

字符串或数字可以作为属性的键, symbol 也可以,它不等同于任何字符串,因而这个以 symbol 为键的属性可以保证不与任何其它属性产生冲突。
 

var obj ={state:11} ;
nativeSymbol =Symbol();
obj[nativeSymbol] = "ok";
console.log(obj[nativeSymbol]);  //ok

上面的情况就可以改为:
 

// 创建一个独一无二的 symbol
var isMoving = Symbol("isMoving");
...
if (element[isMoving]) {
    smoothAnimations(element);
}
element[isMoving] = true;

       Symbol("isMoving")中的 isMoving 被称作描述。element[isMoving]被称作一个以 symbol 为键(symbol-keyed)的属性
它是symbol不是字符串,除此之外它与一个普通的属性没有什么区别。以 symbol 为键的属性属性与数组元素类似,不能被类似 obj.name 的点号法访问,你必须使用方括号访问这些属性。查看属性是否存在: if (isMoving in element),也可以删除属性: deleteelement[isMoving]。同时symbol创建的ismoving只有在当前作用域中才有效,这是symbol的弱封装机制。创建的symbol可在任意对象上使用,无需担心其他代码创建的属性产生冲突。
       symbol 键的设计初衷是避免初衷,因此 JavaScript 中最常见的对象检查的特性会忽略 symbol 键。例如, for-in 循环只会遍历对象的字符串键, symbol 键直接跳过Object.keys(obj)和 Object.getOwnPropertyNames(obj)也是一样。但是 symbols 也不完全是私有的:用新的 APIObject.getOwnPropertySymbols(obj)就可以列出对象的symbol 键。另一个新的 API,Reflect.ownKeys(obj),会同时返回字符串键和 symbol键。


但是,Symbol是什么?

控制台下测试symbol是什么,得到如下结果

symbol被创建后不可更改,不能设置属性,Strict模式下会得到TypeError错误,每个symbol都独一无二

关于Symbol的忠告:symbol 不能被自动转换为字符串,这和语言中的其它类型不同。尝试拼接 symbol 与字符串将得到 TypeError 错误

var mySymbol = Symbol("Symbol");
var str = "your symbol is " +mySymbol;
var str2 = `you symbol is ${mySymbol}`;

//解决方法
var str3 = "your symbol is " +mySymbol.toString();
var str4 = `you symbol is ${mySymbol.toString()}`;

可以通过String(mySymbol)或者mySymbol.toString();解决

获取 symbol 的三种方法

 

  1. 调用Symbol() ,每次返回一个新的唯一Symbol;
  2. 调用Symbol.for(string) 这种方式会访问 symbol 注册表,其中存储了已经存在的一系列 symbol。这种方式与通过 Symbol()定义的独立 symbol 不同, symbol 注册表中的 symbol 是共享的。如果你连续三十次调用 Symbol.for("cat"),每次都会返回相同的 symbol。注册表非常有用,在多个 web 页面或同一个 web 页面的多个模块中经常需要共享一个 symbol;
  3. 使用标准的symbol,例如Symbol.Iterator

symbol 在 ES6 规范中的应用
 

  • 使 instanceof 可扩展,在 ES6 中,表达式 object instanceof constructor 被指定为构造函数的一个方法: constructor[Symbol.hasInstance](object)。这意味着它是可扩展的;
  • 消除新特性和旧代码之间的冲突。破坏问题主要由动态作用域引起,所以 ES6 引入一个特殊的 symbol——Symbol.unscopables, Web 标准可以用这个 symbol 来阻止某些方法别加入到动态作用域中;
  • 支持新的字符串匹配类型。在 ES5 中, str.match(myObject)会尝试将 myObject 转换为正则表达式对象(RegExp)。在 ES6 中,它会首先检查 myObject 是否有一个myObject[Symbol.match](str)方法。


     

本文参考《ES6-In-Depth》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值