Day 26 [其他04] ES6的Symbol竟然那么强大,面试中的加分点啊

文章选自

作者:xiaohesong

连接:https://juejin.im/post/6844903703242080263

原文连结:https://xiaohesong.gitbook.io/today-i-learn/front-end/es6/understanding-es6/symbol#basic

来源:掘金

甚麽是Symbol

Symbol是ES6加进来的,也是属於基本类型(number、string....)

基本用法

可以发现Symbol类型可以当作对象的key

let foo = Symbol('bar')
console.log(typeof foo) // 'symbol'
let testObj = {}
testObj[foo] = '这样可以设置!'
console.log(testObj);

https://ithelp.ithome.com.tw/upload/images/20210201/20124350wn530oMJ35.png

Symbol for

透过这个方法创建时会先在全局里面寻找这个key的Symbol,如果存在则返回此Symbol,不存在则创建并进行全局注册

// 用基本方法创建两个相同key的Symbol会不一样
let first = Symbol('不会一样')
let second = Symbol('不会一样')
console.log(first === second); // fasle

// 用此方法创建的则会一样
let fooA = Symbol.for('居然会一样')
let fooB = Symbol.for('居然会一样')
console.log(fooA === fooB); // true

// 基础方法跟Symbol.for当然也不一样
let barA = Symbol('这样也会不一样')
let barB = Symbol.for('这样也会不一样')
console.log(barA === barB); // false

Symbol keyfor

返回用全局注册Symbol的key

let fooA = Symbol.for("foo");
console.log(Symbol.keyFor(fooA)); // "foo"

let fooB = Symbol.for("foo");
console.log(Symbol.keyFor(fooB)); // "foo"

// 因为没有透过Symbol.for进行全局注册当然找不到
let notKeyCreated = Symbol("我居然会不存在!");
console.log(Symbol.keyFor(notKeyCreated)); // undefined

Symbol 不会被自动转换

可以透过String转型,不过讲真的这样做意义不大

let foo = Symbol('foo')

console.log(String(foo));
console.log(foo.toString())
console.log(foo + '');

https://ithelp.ithome.com.tw/upload/images/20210201/20124350jqizZV3zGj.png

对象里Symbol key的获取

let foo = Symbol('foo')
let obj = {
  // 注意我们要用Symbol当成key,需要要用方括号刮起来
  // 因为需要的是变量foo非字符串foo
  [foo]: 'foo'
}
console.log(Object.keys(obj)) // []
console.log(Object.getOwnPropertyNames(obj)) // []

// ES6新增的方法
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(foo)]

补充

let obj = {
  [foo]: 'foo'
}

这里提到了我们要让

注意我们要用Symbol当成key,需要用方括号刮起来
因为需要的是变量foo非字符串foo

所以以下设置也是为了此目的

let obj = {}
let foo = Symbol('foo')

obj.foo = 'foo'
obj[foo] = 'SymbolFoo'

console.log(obj);

https://ithelp.ithome.com.tw/upload/images/20210201/20124350P76Fxf9Zfv.png

Symbol.hasInstance

每一个函数内部都会有存在这个方法,主要判断一个对象是否为构造函数的实例(即是instanceof)

function User() {}
const Mike = new User
console.log(Mike instanceof User) // true
// 使用函数内部的方法
console.log(User[Symbol.hasInstance](Mike)) // true

自定义instanceof

// 取自MDN
class Array1 {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

console.log([] instanceof Array1);
// expected output: true

Symbol.isConcatSpreadable

以下取自MDN:

内置的方法的参数时是否展开其数组元素。Symbol.isConcatSpreadable`符号用于配置某对象作为Array.prototype.concat

例子

let foo = ['a', 'b', 'c']
let = numeric = [1, 2, 3];

let fooAndNumericA = foo.concat(numeric);

console.log(fooAndNumericA); // 结果: ['a', 'b', 'c', 1, 2, 3]

// 
numeric[Symbol.isConcatSpreadable] = false;

let fooAndNumericB = foo.concat(numeric)
console.log(fooAndNumericB);

https://ithelp.ithome.com.tw/upload/images/20210201/20124350rNsKXOFP3F.png

Symbol.toPrimitive

对象的内置属性,一个对象可以被转换成原始值都是靠他帮忙

该函数被调用时,会被传递hint参数,代表预期想要转换的类型

参数的值有三种

  1. number
  2. string
  3. default

string以及number 模式

number mode:

  • 首先调用valueOf,若是原始类型,那就返回。
  • 若非原始值,那麽就调用toString,如果是原始类型,那就返回
  • 如果都不存在,那麽就报错

string mode 在字符串的情况下,行为略有不同(优先级从高到低)

  • 首先调用toString,如果是原始值,那麽就返回
  • 如果前面不是原始值,那麽就尝试调用valueOf,如果是原始值,那麽就返回
  • 抛出错误

例子

此例子可以观察Symbol.toPrimitive是如何干扰对象转换成原始类型

// 以下改写自MDN
// 没有改写 Symbol.toPrimitive 的对象
var fooA = {};
console.log(fooA / 1); // NaN
console.log(String(fooA)); // "[object Object]"
console.log(fooA + ""); // "[object Object]"

// 声明一个新的对象,并更改了他的 Symbol.toPrimitive 属性
var fooB = {
  [Symbol.toPrimitive](hint) {
    if (hint == "number") {
      return 'number';
    }
    if (hint == "string") {
      return "string";
    }
    return 'default';
  }
};
console.log(fooB / 1); // Nan
console.log(String(fooB)); // string
console.log(fooB + ""); // default


<<:  Day 25 [模块化] 前端模块化:CommonJS,AMD,CMD,ES6

>>:  Day 27 [其他05] 前端必知必会--操作URL的黑科技

[Day. 30] 总结&完赛心得

第12届铁人完赛! 说真实的,原本规划的30天内容大概到第20天就用光了xD 後面10天几乎都是当天...

[DAY25] 用 Azure Machine Learning SDK 注册模型与部署

DAY25 用 Azure Machine Learning SDK 注册模型与部署 之前提过在 A...

Day 13 : 案例分享(4.2) 签核与费用模组 - 签核模组 Base Tier Validation

案例说明及适用场景 即然都以全WEB了,当然一定会有签核的需求 Base Tier Validati...

[LeetCode30] Day26 - 1106. Parsing A Boolean Expression

题目 给一个型别为string的boolean expression,回传结果(true or fa...

Day 10 Compose UI migration 到目前的专案上!

今年的疫情蛮严重的,希望大家都过得安好,希望疫情快点过去,能回到一些线下技术聚会的时光~ 今天要接触...