JS Symbol类型大揭秘,为什么面试都喜欢问?

在JS中,有一个数据类型大家可能用的不太多,但是面试出现的频率很高,那就是ES6引入的Symbol类型。

一、Symbol概述

ES5的对象属性名都是字符串,这很容易造成属性名的冲突。 比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是ES6引入的Symbol的原因。

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

let Sym = Symbol();

console.log(typeof Sym)
// symbol
}

上面代码中,变量s就是独一无二的值。typeof运算符的结果,表明变量s是Symbol数据类型,而不是字符串之类的其它类型。

注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。也就是说,由于Symbol值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

let Sym = new Symbol();

console.log(Sym)
//Uncaught TypeError: Symbol is not a constructor
//at new Symbol (<anonymous>)

Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,注意这个字符串仅仅表示描述而已,有了描述,输出的时候就能够分清,到底是哪一个值。

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"

因此相同参数的Symbol函数的返回值是不相等的。

let s1 = Symbol('foo');
let s2 = Symbol('foo');

console.log(s1 === s2)
//false

Symbol值不能与其它类型的值进行运算,会报错。

let sym = Symbol('My symbol');

"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${
      
      sym}`
// TypeError: can't convert symbol to string

但是,Symbol值可以显式转为字符串。

let sym = Symbol('My symbol');

String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'

另外,Symbol值也可以转为布尔值,但是不能转为数值。

let sym = Symbol();
Boolean(sym) // true
!sym  // false

if (sym) {
    
    
  // ...
}
Number(sym) // TypeError
sym + 2 // TypeError

二、Symbol作为属性名

由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

let mySymbol = Symbol("mySymbol");
let a = {
    
    
	mySymbol:"name"
};
a[mySymbol] = 'Hello!';

console.log(a)

在这里插入图片描述

注意,Symbol值作为对象属性名时,不能用点运算符。

const mySymbol = Symbol();
const a = {
    
    };
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"

上面代码中,因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值,导致a的属性名实际上是一个字符串,而不是一个Symbol值。

同理,在对象的内部,使用Symbol值定义属性时,Symbol值必须放在方括号之中。

let s = Symbol();
let obj = {
    
    
  [s]: function (arg) {
    
     ... }
};

obj[s](123);

上面代码中,如果s不放在方括号中,该属性的键名就是字符串s,而不是s所代表的那个Symbol值。

QQ:505417246
微信:18331092918
微信公众号:Code程序人生
个人博客:https://Creator12333.github.io(详细总结一些面试题,以及前端进阶的内容,CSDN写偏基础的内容)

Supongo que te gusta

Origin blog.csdn.net/m0_46171043/article/details/117855428
Recomendado
Clasificación