深刻理解ES6之《Symbol》

建立Symbol及辨别方法

Symbol是原始值,所以调用new Symbol会致使程序抛出错误数组

let firstName = Symbol()
let person = {}
person[firstName] = "angela"
console.log(person[firstName])

使用typeof来辨别其类型函数

let symbol=Symbol('this is test description')
console.log(typeof symbol)//symbol

Symbol可用于计算对象字面量属性名、Object.defineProperty、Object.definePropertiesui

若是想建立一个共享的Symbol,可以使用Symbol.for方法this

let uid = Symbol.for('uid')
let object = {
  [uid]: '12345'
}
console.log(object[uid])//12345
console.log(uid)//Symbol(uid)
let uid2 = Symbol.for('uid')
console.log(uid === uid2)//true
console.log(object[uid2])//12345
console.log(uid2)//Symbol(uid)

Symbol.keyFor方法在Symbol全局注册表中检索与Symbol有关的键spa

let uid = Symbol.for('uid')
console.log(Symbol.keyFor(uid))//uid
let uid2 = Symbol.for('uid')
console.log(Symbol.keyFor(uid2))//uid
let uid3=Symbol('uid')
console.log(Symbol.keyFor(uid3))//undefined

Symbol全局注册表是一个相似全局做用域的共享环境,也就是说你不能假设目前环境中存在哪些键prototype

Symbol与类型强制转换

不能将Symbol强制转换成数字类型,Symbol也不能够被转换成字符串code

let uid = Symbol.for('uid')
let desc = uid + ""//报错 Uncaught TypeError: Cannot convert a Symbol value to a string
let uid = Symbol.for('uid')
let desc = uid / 1//报错  Uncaught TypeError: Cannot convert a Symbol value to a number

可是却能够像下面这样使用对象

let uid = Symbol.for('uid')
let desc = String(uid)
console.log(desc)//Symbol(uid)

Symbol属性检索

Object.getOwnPropertySymbolsblog

let uid = Symbol.for('uid')
let object = {
  [uid]: '12345'
}
let symbols=Object.getOwnPropertySymbols(object)

Symbol.hasInstance

Symbol.hasInstance只接受一个参数,即要检查的值
每一个函数都有Symbol.hasInstance方法,用于肯定对象是否为函数实例,该方法在Function.prototype中定义,该方法被定义不为可写、不可配置、不可枚举图片

let obj = []
//obj instanceof Array //下面一句代码与此句功能等价
Array[Symbol.hasInstance](obj)//true

咱们能够经过Object.defineProperty方法改写一个不可写属性
因此其实能够重写全部内建函数(如Date和Error)默认的Symbol.hasInstance属性

function SpecialNumber() { }
Object.defineProperty(SpecialNumber, Symbol.hasInstance, {
  value: function (v) {
    return (v instanceof Number) && (v >= 1 && v <= 100)
  }
})
var two = new Number(2),
  zero = new Number(0);
console.log(two instanceof SpecialNumber)//true
console.log(zero instanceof SpecialNumber)//false

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable属性值为true代表属性值应看成为独立元素添加到数组中

let c1 = ['red', 'green'],
  c2 = c1.concat(['blue', 'black'], 'yellow')
console.log(c2)//["red", "green", "blue", "black", "yellow"]

为何上面一段代码结果是["red", "green", "blue", "black", "yellow"]而不是["red", "green", ["blue", "black"], "yellow"]?
图片描述
若是把上面的代码稍微改一下,结果就彻底不同了

let collection = {
  0: 'hello',
  1: 'world',
  2: 'demo',
  3: 'test',
  [Symbol.isConcatSpreadable]: true,
  length: 4
}
let msg = ['Hi'].concat(collection)
console.log(msg)//["Hi", "hello", "world", "demo", "test"]

Symbol.match,Symbol.replace,Symbol.search,Symbol.split

let hasLenOf10 = {
  [Symbol.match](v) {
    return v.length === 10 ? [v.substring(0, 10)] : null
  },
  [Symbol.replace](v, replacement) {
    return v.length === 10 ? replacement + v.substring(10) : v;
  },
  [Symbol.search](v) {
    return v.length === 10 ? 0 : -1
  },
  [Symbol.split](v) {
    return v.length === 10 ? ["", ""] : [v]
  }
}
let msg1 = 'Hello world',
  msg2 = 'Hello John';
console.log(msg1.match(hasLenOf10))//null
console.log(msg2.match(hasLenOf10))//[Hello John]
console.log(msg1.replace(hasLenOf10))//Hello world
console.log(msg2.replace(hasLenOf10))//undefined
console.log(msg1.search(hasLenOf10))//-1
console.log(msg2.search(hasLenOf10))//0
console.log(msg1.split(hasLenOf10))//["Hello world"]
console.log(msg2.split(hasLenOf10))//["",""]

Symbol.toPrimitive

在执行特定操做时,常常会尝试将对象转换到相应的原始值
Symbol.toPrimitive被定义在每个标准类型的原型上,而且规定了当对象被转换为原始值时应该执行的操做
每当执行类型转换总会调用Symbol.toPrimitive方法并传入一个值做为参数,这个值在规范中被称做类型提示hint,类型提示参数只有三种选择number、string、default

function Temperature(degree) {
  this.degree = degree
}
Temperature.prototype[Symbol.toPrimitive] = function (hint) {
  switch (hint) {
    case "string":
      return this.degree + '\u00b0';
    case "number":
      return this.degree;
    case "default":
      return this.degree + " degrees"
  }
}
var freezing = new Temperature(32)
console.log(freezing + "!")//32 degrees!
console.log(freezing / 2)//16
console.log(String(freezing))//32°

Symbol.toStringTag

之前判断一个对象的类型通常都是这样

function isArray(value) {
  return Object.prototype.toString.call(value) === "[object Array]"
}

ES6中咱们能够自定义对象字符串标签

function Person(name) {
  this.name = name
}
Person.prototype[Symbol.toStringTag] = "Person"
Person.prototype.toString = function () {
  return this.name
}
var me = new Person('angela')
console.log(me.toString())//angela
console.log(Object.prototype.toString.call(me))//[object Person]

若是咱们不重写toString方法,则me.toString返回的值就是[object Person]咱们能够给Person.prototype[Symbol.toStringTag]赋任意值,固然也能够修改原生对象的字符串标签

相关文章
相关标签/搜索