【深入理解ES6】Symbol

创建Symbol

新增基础类型 Symbol,用于解决 私有属性 问题

let firstName = Symbol()
let person = {}

person[firstName] = 'Nicholas'
console.log(person["firstName"])

注意, Symbol是原始值,不能 new Symbol()构建实例,只能是new Object(【Symbol 值】)

 Symbol 接受可选参数,用于描述该  Symbol 

内部存储在 [[Description]] 属性中,所以只有 Symbol 的toString 方法能读取

而 console.log 隐式调用 toString 方法

let firstName = Symbol('first name')
let person = {}

person[firstName] = 'abc'

console.log(person)

Symbol辨识

通过 typeof,返回值为 symbol

let firstName = Symbol('first name')
console.log(typeof firstName)

Symbol的使用方法

  • 对象中括号引用
  • 对象字面量
  • Object.defineProperty
let firstName = Symbol('first name')
let person_1 = {}

person_1[firstName] = 'person111'

let person_2 = {
  [firstName]: 123
}

Object.defineProperty(person_2, firstName, { writable: false })

let lastName = Symbol('last name')

Object.defineProperties(person, {
  [lastName]: {
    value: 111,
    writable: false
  }
})

Symbol的共享体系

Symbol.for() 会在 Symbol全局注册表 中查找

  • 存在,则返回对应的 Symbol 值
  • 不存在,则新创建一个 Symbol 存入注册表
let uid = Symbol.for("uid")
let object = {}

object[uid] = 1234

console.log(object) // { [Symbol(uid)]: 1234 }

let uid2 = Symbol.for('uid')

console.log(uid === uid2) // true
console.log(uid2, object[uid2]) // Symbol(uid) 1234

Symbol.keyFor 在 Symbol全局注册表 中检索 Symbol 相关的键值

let uid = Symbol.for("uid")
console.log(Symbol.keyFor(uid))

let uid2 = Symbol.for("uid")
console.log(Symbol.keyFor(uid2))

let uid3 = Symbol('uid')
console.log(Symbol.keyFor(uid3))

Symbol 的类型转换

  • 其他类型的值不存在逻辑等价
  • 尤其Number 和 String ,会报错
  • String()对象实例化,内部调用了Symbol.toString()
let uid = Symbol.for('uid'),
  desc = String(uid) // uid.toString()

console.log(desc) // 'Symbol(uid)'

Symbol 属性检索

ES5中

Object.keys() 可枚举属性

Object.getOwnPropertyNames() 对象的所有属性

以上一律不支持对象中 Symbol 属性

ES6新增 Object.getOwnPropertySymbols 返回对象中的所有 Symbol 属性

let uid = Symbol('uid')
let password = Symbol('password')

let obj = {
  a: 123,
  b: 'asd',
  [uid]: '12',
  [password]: 123,
}

// [ 'a', 'b' ]
console.log(Object.getOwnPropertyNames(obj)) 

// [ Symbol(uid), Symbol(password) ]
console.log(Object.getOwnPropertySymbols(obj)) 



通过 well-know Symbol 暴露内部操作

Symbol.hasInstance

用于确定对象是否为函数的实例(即 obj instanceof Object)

function Test() {}

Object.defineProperty(Test, Symbol.hasInstance, {
  value: function (num) {
    return (num instanceof Number) && (num > 0 && num < 100)
  }
})

let test = new Number(1)
let test_0 = new Number(0)

console.log(test instanceof Test)
console.log(test_0 instanceof Test)

let a = new Number('123') // 123 === a flase

let b = Number('123')     // 123 === b true

a instanceof Number       // true

b instanceof Number       // false

 Symbol.isConcatSpreadable

用于配置某对象作为Array.prototype.concat()方法的参数时是否展开其数组元素。

标识对象是否具有 length 和 数字键

let a = {
  2: '123',
  3: 'awe',
  'test': 'test',
  length: 5,
  [Symbol.isConcatSpreadable]: true
}

let arr = ['0', '1', '2']

let newArr = arr.concat(a)

console.log(newArr)
// [ '0', '1', '2', <2 empty items>, '123', 'awe', <1 empty item> ]

match && replace && search && split

  • String.match(reg) 字符串是否匹配正则表达式

  • String.replace(reg, replacement) 字符串匹配正则表达式部分内容替换

  • String.search(reg) 字符串匹配正则表达式索引位置的字符

  • String.split(reg) 字符串以正则表达式符合分割

// 等价于 /^.{10}$/
let hasLengthOf10 = {
  [Symbol.match]: function (value) {
    return value.length === 10 ? [value] : null
  },
  [Symbol.replace]: function (value, replacement) {
    return value.length === 10 ? replacement : value
  },
  [Symbol.search]: function (value) {
    return value.length === 10 ? 0 : -1
  },
  [Symbol.split]: function (value) {
    return value.length === 10 ? [,] : [value]
  }
}

const message_1 = "Hello world", // 11 字符
  message_2 = "Hello John" // 10 字符

const match_1 = message_1.match(hasLengthOf10),
  match_2 = message_2.match(hasLengthOf10)

print("match:", match_1, match_2)

const replace_1 = message_1.replace(hasLengthOf10, '1'),
  replace_2 = message_2.replace(hasLengthOf10, '1')

print("replace: ", replace_1, replace_2)

const search_1 = message_1.replace(hasLengthOf10),
  search_2 = message_2.replace(hasLengthOf10)

print("search: ", search_1, search_2)

const split_1 = message_1.split(hasLengthOf10),
  split_2 = message_2.split(hasLengthOf10)

print("split: ", split_1, split_1)

function print(str, ...arg) {
  console.log(str)
  arg.forEach((item, index) => {
    console.log(index, item)
  })
  console.log('-'.repeat(10))
}

Symbol.toPrimitive

会将对象转换为对应的原始值

  • 数字模式
    • 首先用 valueOf() 方法,如果结果为原始值,则返回
    • 其次才是 toString() 方法,如果结果为原始值,则返回
    • 报错
  • 字符串模式
    • 首先用 toString() 方法,如果结果为原始值,则返回
    • 其次才是  toString() 方法,如果结果为原始值,则返回
    • 报错
  • Default模式
    • 多数按照Number模式
    • Date对象则采用 string 模式
function Template(degrees) {
  this.degrees = degrees
}

Template.prototype[Symbol.toPrimitive] = function (hint) {
  switch (hint) {
    case 'string':
      return this.degrees + '\u00b0';
    case 'number':
      return this.degrees;
    case 'default':
      return this.degrees + ' degrees'
  }
}

const freezing = new Template(32)

console.log(freezing + '!') // "32 degrees!"
console.log(freezing / 2) // 16
console.log(String(freezing)) // "32°"



Symbol.toStringTag

更改 Object.prototype.toString.call 的返回

function Person(name) {
  this.name = name
}

Person.prototype[Symbol.toStringTag] = "Person"

let person = new Person('wgf')

console.log(Object.prototype.toString.call(person)) // [object Person]

ES5 之前JSON是由 Douglas Crockfound 的 json2.js 提供

在出现ES默认全局JSON对象后,代码中需要判断 JSON 的来源

function supportsNativeJSON() {
  return JSON !== 'undefined' && 
    Object.prototype.toString.call(JSON) === '[object JSON]'
}

Symbol.unscropable

由于 ES6 语法向下兼容,解决 with 语句绑定问题

with语句

 等价于调用了两次 colors.push()

 但是 ES6 数组引入新的方法 values,会导致上述代码歧义

 (原意应为:调用 colors 数组外部变量)

var values = [1, 2, 3],
  colors = ['red', 'yellow', 'blue'],
  color = 'black'

with (colors) {
  push(color)
  push(...values)
}

console.log(colors)

默认内置

通过手动设置该属性,with 语句将不再创建这些方法的绑定,从而支持老代码的运行

Array.prototype[Symbol.unscopables] = Object.assign(Object.create(null), {
  copyWithin: true,
  entries: true,
  fill: true,
  find: true,
  findIndex: true,
  keys: true,
  values: true
})

注意:除非使用 with 语句且正在修改代码库中的已有的代码,否则不要为自己的对象定义 Symbol.unscopable

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ES6是ECMAScript 2015的简称,是JavaScript的一个重要的更新版本。深入理解ES6 PDF是一本通过深入研究ES6标准来理解其中各种语法和特性的书籍。 这本书分为十八章,从ES6的基础语法和新特性入手,详细讲解了ES6的语法、语义和使用方法。其中包括了箭头函数、简化的对象字面量、模板字面量、解析器、新的控制结构、类和继承、生成器和迭代器、异步操作、Symbol和迭代器、集合和迭代器、Map和Set、新的数组方法、Promise和异步操作、代理和反射、模块化和导入机制,每一章都是围绕特定的内容展开细致的解读。 对于学习ES6的开发者来说,这本书是一份非常有价值的资料。读者可以从中深入了解ES6的语言架构和语法规范,更加深入理解JavaScript的基础和高级语言特性。对于从ES5升级到ES6的开发者来说,该书是学习ES6语言的最佳手册,还可以通过实例代码快速掌握ES6的语言特性。 总之,深入理解ES6 PDF是一本非常专业且详细的技术书籍,可以帮助读者深入了解ES6语言特性,并掌握新的编程技巧。 ### 回答2: ES6是Javascript的下一代语言标准,它引入了许多新的语法、特性和API,使得编程变得更加简单、高效、灵活和快捷。深入理解ES6 PDF是一本ES6入门指南,它帮助读者系统地学习ES6的核心知识和技能,了解ES6的语法、模块、类、迭代器、生成器、Promise等核心概念及其实践应用。 阅读深入理解ES6 PDF,首先需要了解ES6的基本语法和新特性,包括箭头函数、模板字符串、解构赋值、默认参数、rest参数等。其次,需要学习ES6的模块化设计,了解如何实现模块导出、导入、依赖管理等功能,以便更好地组织代码和提高代码的复用性。另外,深入理解ES6 PDF也介绍了ES6的面向对象编程特性,包括类的声明、方法的定义、继承、多态等,以及ES6的迭代器、生成器、Promise等核心概念及其实践应用,使得读者可以更加深入地掌握ES6的精髓和应用。 综上所述,深入理解ES6 PDF是一本非常好的ES6入门指南,它帮助读者了解ES6的核心知识和技能,带领读者建立ES6的编程思想和风格,以便更好地应对现代Web应用开发的挑战,同时也是学习ES6语言的必备指南。 ### 回答3: 《深入理解ES6》是一本详细介绍ES6新特性的书籍。它主要介绍了模板字符串、解构赋值、箭头函数、类、模块化开发等ES6的新语法。通过深入阅读这本书,能够更好地理解和运用ES6的新特性。 其中,模板字符串是ES6引入的一个非常重要的新特性,它可以让我们更方便地处理字符串拼接和换行,同时还支持常用的字符串操作方法。 解构赋值则是ES6中的另一个重要特性,它可以让我们更快捷地从一个对象或数组中提取出需要的值,这对于提高代码的可读性和复用性都非常有帮助。 箭头函数是ES6中的又一个新特性,它可以让我们更愉悦地编写函数,并且它的this指向也更加方便和易懂。同时也是优化了ES5语言中函数语法臃肿和拖沓的问题。 类是ES6中一个重要的新特性,它可以让我们更加方便地实现面向对象编程,这是在ES5中较为繁琐的过程,同时也减少了ES5类的一些使用致命局限。 最后,模块化开发也是ES6中的一个重要特性,它可以让我们更加方便地组织和管理代码,同时也减少了代码间的相互污染,使得代码更加易于维护和扩展。 总之,《深入理解ES6》这本书为我们深入了解ES6的新特性提供了很好的指导和方向,并且还有配套的演示代码,非常值得一读。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值