- A+
JS第七种数据类型Symbol详解
一、什么是Symbol?
Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值。它是JavaScript中的第 七种数据类型,与undefined、null、Number(数值)、String(字符串)、Boolean(布尔值)、 Object(对象)并列。
Symbol特点:
- Symbol的值是唯一的,用来解决命名冲突问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
基本用法:
let a = Symbol("末晨曦吖"); console.log(a); // Symbol(末晨曦吖) console.log(typeof a); //symbol // 相同参数 Symbol() 返回的值不相等 let b = Symbol("末晨曦吖"); console.log(a === b); //false
为什么相同参数 Symbol() 返回的值不相等???
因为使用Symbol()创建一个Symbol类型的值并赋值给a变量后,你就得到了一个在内存中独一无二的值。现在除了通过变量a,任何人在任何作用域内都无法重新创建出这个值。所以就算我们通过相同参数创建的b,结果还是不相等的。
尽管a和b都是使用Symbol()创建出来的,但是它们在内存中看起来却是这样的:
实际上,a变量拿到了内存中某块内存的唯一引用(这里所说的引用,其实就是该内存的地址)。如果不借助a变量,你不可能再得到这个地址。因此:
a !== b; //a和b持有的是两块内存的引用 const c = a; //手动把a里保存的地址保存在c变量中 a === c; //c和a现在指向同一块内存,因为它们保存了同样的地址
这种行为看似难以理解,但其实它与对象遵循相同的规则,如:
let a = {}; let b = {}; a !== b; //a和b各自被分配了不同的内存,因此它们保存了不同的地址 //借助变量a,变量c拿到了a指向的那个对象的地址,因此两者相等 let c = a; a === c;
但是对于同为基本数据类型的字符串来说,它不遵循类似的规则。比如:
let a = "123"; let b = "123"; a === b; //返回true。两者在常量区引用同一个字符串
我们首先通过变量a在内存中创建了字符串“123”,然后在不借助变量a的情况下,又通过var b = "123"拿到了对“123”这个字符串的引用,两者指向内存中的同一块内存地址。
因此我们说,a无法确保别的变量无法拿到它保存的地址(前提是不通过a)。但是对于var a = Symbol()这样的语句,a变量内保存的值是唯一的,因为除了借助a变量,你永远无法得到a中保存的值。这也是Symbol的本质。
作为属性名的Symbol
let mySymbol = Symbol(); // 第一种写法 let a = {}; a[mySymbol] = 'Hello!'; // 第二种写法 let a = { [mySymbol]: 'Hello!' }; // 第三种写法 let a = {}; Object.defineProperty(a, mySymbol, { value: 'Hello!' }); // 以上写法都得到同样结果 a[mySymbol] // "Hello!" 注意,Symbol值作为对象属性名时,不能用点运算符。 let a = {}; let name = Symbol(); a.name = 'lili'; a[name] = 'lucy'; console.log(a.name,a[name]);//lili,lucy Symbol值作为属性名时,该属性还是公开属性,不是私有属性。
二、Symbol中的方法
1、Symbol.for()
我们知道Symbo()创建的两个变量永远不会是相同的。那么如果我们需要重新使用同一个Symbol怎么办,总不能需要挨个去进行比较吧。还好,es6为我们提供了Symbol.for()方法。
参数是symbol类型的描述信息,不同于Symbol(),这个而参数只能是字符串或者是undefined,若已经创建了则返回这个symbol,否则就进行创建并将这个新的symbol返回,代码如下
let name = Symbol.for("末晨曦"); let name1 = Symbol.for("末晨曦"); console.log(name === name1); // true
请注意,我们在使用创建描述信息为"末晨曦"的变量的时候,使用的是for,而不是Symbol(),倘若使用Symbol()进行首次创建,for会再次创建一次,二者不会相等,代码如下:
let name = Symbol("末晨曦"); let name1 = Symbol.for("末晨曦"); console.log(name === name1); // false
原因在于Symbol.for()会有一个登记机制,使用for只会对通过for创建的symbol进行检查,不会对Symbol()创建的进行检查。
2、Symbol.keyFor()
这个方法参数是一个通过Symbol.for()创建的symbol类型变量,返回这个symbol变量的描述信息。
let name = Symbol.for("末晨曦"); console.log(Symbol.keyFor(name)); // "末晨曦" let name1 = Symbol("末晨曦"); console.log(Symbol.keyFor(name1)); // undefined 不能查找Symbol()创建的变量