【每日一题】ES6 中为什么要使用 Symbol

关注「松宝写代码」,精选好文,每日面试题

加入我们一起学习,day day up

作者:saucxs | songEagle

来源:原创

一、前言

2020.12.23 立的 flag,每日一题,题目类型不限制,涉及到JavaScript,Node,Vue,React,浏览器,http,算法等领域。

本文是第2道:ES6中为什么要使用Symbol?

二、ES6中为什么要使用Symbol?

1、简述ES6中Symbol的概念

ES6中已经有6种数据类型:

  • Undefined
  • Null
  • 布尔值
  • 字符串
  • 数值
  • 对象

但是在ES6种新加入一种新的数据类型Symbol。

Symbol表示独一无二的值。

// 没有参数的情况
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false

// 有参数的情况
var s1 = Symbol('saucxs');
var s2 = Symbol('saucxs');
s1 === s2 // false

[图片上传失败...(image-34d6a9-1610966878673)]

需要说明一下:这里的字符'saucxs'是该Symbol的一个描述,但是并非两个参数都是'saucxs'。

2、简述Symbol的特性

  • 特性1:Symbol 值通过 Symbol 函数生成,使用 typeof,结果为 "symbol"
var a = Symbol();
console.log(typeof a); // "symbol"
  • 特性2:Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。

  • 特性3:instanceof 的结果为 false

var a = Symbol('foo');
console.log(a instanceof Symbol); // false
  • 特性4:Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
var a = Symbol('saucxs');
console.log(a); // Symbol(saucxs)
  • 特性5:如果 Symbol 的参数是一个对象,就会调用该对象的 toString 方法,将其转为字符串,然后才生成一个 Symbol 值。
const obj = {
  toString() {
    return 'abc';
  }
};
const a = Symbol(obj);   // Symbol(abc)
  • 特性6:如果 Symbol 的参数是一个对象,就会调用该对象的 toString 方法,将其转为字符串,然后才生成一个 Symbol 值。
// 没有参数的情况
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false

// 有参数的情况
var s1 = Symbol('saucxs');
var s2 = Symbol('saucxs');
s1 === s2 // false
  • 特性7:Symbol 值不能与其他类型的值进行运算,会报错。
var a = Symbol('saucxs');

console.log(`I am ${a}`); // TypeError: can't convert symbol to string
  • 特性8:Symbol 值可以显式转为字符串。
const f = Symbol('saucxs')
f.toString()    // "Symbol(saucxs)"
String(f)       // "Symbol(saucxs)"
  • 特性9:Symbol 值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性。
var mySymbol = Symbol();

// 第一种写法
var a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
var a = {
  [mySymbol]: 'Hello!'
};

// 第三种写法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
console.log(a[mySymbol]); // "Hello!"
  • 特性10:Symbol 作为属性名,该属性不会出现在 for...in、for...of 循环中,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有 Symbol 属性名。
var obj = {};
var a = Symbol('a');
var b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

var objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols);
// [Symbol(a), Symbol(b)]
  • 特性11:使用同一个 Symbol 值,可以使用 Symbol.for。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
var s1 = Symbol.for('saucxs');
var s2 = Symbol.for('saucxs');

console.log(s1 === s2); // true
  • 特性12: Symbol.keyFor 方法返回一个已登记的 Symbol 类型值的 key。
var s1 = Symbol.for("saucxs");
console.log(Symbol.keyFor(s1)); // "saucxs"

var s2 = Symbol("saucxs");
console.log(Symbol.keyFor(s2) ); // undefined

3、为什么要使用Symbol?

比如有这样一种场景,我们想区分两个属性,其实我们并不在意,这两个属性值究竟是什么,我们在意的是,这两个属性绝对要区分开来!
例如:

const shapeType = { triangle: 'Triangle'};
function getArea(shape, options) { 
    var area = 0; 
    switch (shape) { 
      case shapeType.triangle:
      area = .5 * options.width * options.height; 
      break; 
    } 
    return area;
}

getArea(shapeType.triangle, { width: 200, height: 200 });

这个时候,我们仅仅是想区分各种形状,因为不同的形状用不同的计算面积的公式。
这里使用的是triangle的名字叫做‘Triangle’,而是事实上我们不想对triangle去特地取个名,我们只想要区分triangle这个形状不同于任何其他形状,那么这个时候Symbol就派上用场啦!

const shapeType = {
   triangle: Symbol()
};

也就是说,我们不用非要去给变量赋一个字符串的值,去区分它和别的变量的值不同,因为去给每个变量取个语义化而又不同的值是一件伤脑子的事,当我们只需要知道每个变量的值都是百分百不同的即可,这时候我们就可以用Symbol。

还有可以运用在类的私有变量和私有方法中。

谢谢支持

1、文章喜欢的话可以「分享,点赞,在看」三连哦。

2、作者昵称:saucxs,songEagle,松宝写代码。「松宝写代码」作者,每日一题,实验室等。一个爱好折腾,致力于全栈,正在努力成长的字节跳动工程师,星辰大海,未来可期。内推字节跳动各个部门各个岗位。

3、长按下面图片,关注「松宝写代码」,是获取开发知识体系构建,精选文章,项目实战,实验室,每日一道面试题,进阶学习,思考职业发展,涉及到JavaScript,Node,Vue,React,浏览器,http等领域,希望可以帮助到你,我们一起成长~

[图片上传失败...(image-803791-1610966878673)]

字节内推福利

  • 回复「校招」获取内推码
  • 回复「社招」获取内推
  • 回复「实习生」获取内推

后续会有更多福利

学习资料福利

回复「算法」获取算法学习资料

往期「每日一题」

1、JavaScript && ES6

  • 第 22 题:【每日一题】(22题)面试官问:var与const,let的主要区别是什么?

  • 第 21 题:【每日一题】(21题)面试官问:谈谈JS中的 this 的绑定?

  • 第 20 题:【每日一题】(20题)面试官问:谈谈JS中的 webSockets 的理解?

  • 第 19 题:【每日一题】面试官问:谈谈JS中的 XMLHttpRequest 对象的理解?

  • 第 18 题:【每日一题】面试官问:JS中的 Ajax 跨域与扩展 Comet ?

  • 第 17 题:【每日一题】(17题)面试官问:JS中事件流,事件处理程序,事件对象的理解?

  • 第 16 题:【每日一题】面试官问:JS中如何全面进行客户端检测?

  • 第 15 题:【每日一题】面试官问:JS类型判断有哪几种方法?

  • 第 14 题:【每日一题】面试官问:谈谈你对JS对象的创建和引申

  • 第 13 题[每日一题]面试官问:['1', '2', '3'].map(parseInt)输出,原因,以及延伸?

  • 第 12 题[每日一题]面试官问:JS引擎的执行过程(二)

  • 第 11 题[每日一题]面试官问:JS引擎的执行过程(一)

  • 第 10 题[每日一题]面试官问:详细说一下JS数据类型

  • 第 8 题[每日一题]面试官问:谈谈你对ES6的proxy的理解?

  • 第 7 题[每日一题]面试官问:for in和for of 的区别和原理?

  • 第 6 题[每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?

  • 第 3 道「「每日一题」面试官问你对 Promise 的理解?可能是需要你能手动实现各个特性」

  • 第 2 道「[每日一题]ES6 中为什么要使用 Symbol?」

2、浏览器

  • 第 9 题[每日一题]requestAnimationFrame不香吗?

3、Vue

  • 第 5 道「每日一题」到底该如何回答:vue数据绑定的实现原理?

4、算法

  • 第 26 道【每日一题】(26题)算法题:最长公共前缀?

  • 第 25 道【每日一题】(25题)算法题:堆数据结构-前 K 个高频元素?

  • 第 24 道【每日一题】(24题)算法题:贪心算法-环游世界之如何加油?

  • 第 4 道「每日一题」与面试官手撕代码:如何科学高效的寻找重复元素?

5、Http

  • 第 1 道「一道面试题是如何引发深层次的灵魂拷问?」

6、Node

  • 第 23 道【每日一题】(23题)面试官问:详细描述事件循环Event Loop?

你可能感兴趣的:(【每日一题】ES6 中为什么要使用 Symbol)