JavaScript ES6新增语法相关个人总结(二)

第7种数据类型,Symbol

Symbol 的值是唯一的,用来解决命名冲突的问题
Symbol 值不能与其他数据进行运算
Symbol 定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys 来获取对象的所有键名

- 代码例:

// 创建Symbol
let s = Symbol()
console.log(s, typeof s) // Symbol()  'symbol'

// 创建Symbol时写入名称,相当于注释名
let s2 = Symbol('name')
let s3 = Symbol('name')
console.log(s2 === s3) // false,每个symbol都是唯一的,不会完全相等

// Symbol.for创建
let s4 = Symbol.for('age')
let s5 = Symbol.for('age')
console.log(s4 === s5) // true,Symbol.for创建的,只要其中的标识值相同,例:'age',那么被创建的symbol就完全相等

// 创建的symbol不能进行运算,以下操作都会报错
let res1 = s + 100
let res2 = s > 100
let res3 = s + '你好'

- Symbol创建对象属性

- 代码例:

let obj = {...}

// 在不知道以上对象中含有哪些属性时,使用Symbol对其创建属性
// 可以保证绝对的唯一性,且不会对原本对象里的属性造成影响
// 方法1
let methods = {
  fn: Symbol(),
  fn2: Symbol()
}
obj[methods.fn] = function() {
  console.log('fn()')
}
obj[methods.fn2] = function() {
  console.log('fn2()')
}

// 方法2
let obj2 = {
  name: 'sky',
  [Symbol('fn')]: function(){
	console.log('fn()')
  },
  [Symbol('fn2')]: function(){
	console.log('fn2()')
  }
}

- Symbol内置的值

Symbol内置了11种值,这些值指向语言内部使用的方法,不同的方法会在特定的场景下自动执行。

方法名说明
Symbol.hasInstance当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法
Symbol.isConcatSpreadable对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。
Symbol.species创建衍生对象时,会使用该属性
Symbol.match当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。
Symbol.replace当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。
Symbol.search当该对象被 str.search (myObject)方法调用时,会返回该方法的返回值。
Symbol.split当该对象被 str.split(myObject)方法调用时,会返回该方法的返回值。
Symbol.iterator对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器
Symbol.toPrimitive该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
Symbol. toStringTag在该对象上面调用 toString 方法时,返回该方法的返回值
Symbol. unscopables该对象指定了使用 with 关键字时,哪些属性会被 with环境排除。

迭代器,for…of

- 基本使用及实现原理

- 代码例:

// 声明数组
const arr = ['sky', 'tom', 'jack', 'joe']

// for...in
for(let i in arr){
  console.log(i) // 返回数组索引下标,依次输出 0 1 2 3
}

// for...of
for(let j of arr){
  console.log(j) // 返回数组内的每个值,依次输出 'sky' 'tom' 'jack' 'joe'
}

对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器

实现原理:

  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
  • 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
  • 每调用 next 方法返回一个包含 value 和 done 属性的对象

- 代码例:

// 声明数组
const arr = ['sky', 'tom', 'jack', 'joe']

// arr数组有个Symbol.iterator方法,我们用一个变量来接收这个方法的返回结果
let iterator = arr[Symbol.iterator]()

// 而这个返回对象内,有个next方法
// 执行该方法会依次指向该数据结构内的成员,返回一个包含value和done属性的对象
console.log(iterator.next()) // {value: 'sky', done: false}
console.log(iterator.next()) // {value: 'tom', done: false}
console.log(iterator.next()) // {value: 'jack', done: false}
console.log(iterator.next()) // {value: 'joe', done: false}
console.log(iterator.next()) // {value: undefined, done: true}

- 使用迭代器自定义遍历对象

- 代码例:

// 创建一个对象,包含数组
const obj1 = {
  name: 'sky',
  arr: ['joe', 'tom', 'jack', 'bob']
}
// 遍历该对象
for(let i of obj1){
  console.log(i)
}

// 由于for...of遍历的是数组,无法直接遍历对象,因此以上代码会报错
// 我们需要在该对象中自定义需要遍历的数组,才能遍历返回正确结果

// 创建一个对象,包含数组
const obj2 = {
  name: 'sky',
  arr: ['joe', 'tom', 'jack', 'bob'],
  // 在需要遍历的对象内,自定义创建Symbol.iterator方法
  [Symbol.iterator]() {
    // this指向
    let _this = this
	// index索引变量
	let index = 0
	// 需要遍历的数组长度
	let length = this.arr.length
    // Symbol.iterator方法内会返回一个对象
	return{
	  // 返回对象内包含一个next方法
	  next(){
	  	// next方法内自定义需要遍历的数组对象
	  	if(index < length){
	  	  // next 方法返回一个包含 value 和 done 属性的对象
	  	  const result = {value: _this.arr[index], done: false}
	  	  // index自增
	  	  index++
	  	  // 返回对象
	  	  return result
	  	}else{
	  	  return {value: undefined, done: true}
	  	}
	  }
	}
  }
  
}
// 遍历该对象
for(let j of obj2){
  console.log(j)  // 返回对象内arr数组的值,依次输出 'joe', 'tom', 'jack', 'bob'
}

生成器函数

生成器就是一个特殊的函数

- 代码例:

// 创建一个生成器函数,*号靠左靠右都没关系
function * gen(){
  console.log('hello')
}
// 直接执行该函数,内部语句是不执行的
gen()
// 生成器函数的返回结果就是一个迭代器对象
let iterator = gen()
// 用其中的next方法才能运行语句
console.log(iterator.next()) // 'hello'

// yield分隔符,可以用来控制分隔每次执行next方法时,所需要执行的语句
function * gen2(){
  console.log(111) // 第一次next方法执行的语句
  yield '第一段执行完毕'
  console.log(222) // 第二次next方法执行的语句
  yield '第二段执行完毕'
  console.log(333) // 第三次next方法执行的语句
  yield '第三段执行完毕,还有最后一段未执行'
  console.log(444) // 第四次next方法执行的语句
}

let iterator2 = gen2()
console.log(iterator2.next()) // {value: '第一段执行完毕', done: false}
console.log(iterator2.next()) // {value: '第二段执行完毕', done: false}
console.log(iterator2.next()) // {value: '第三段执行完毕', done: false}
console.log(iterator2.next()) // {value: undefined, done: true}

- 生成器函数传参

- 代码例:

// 创建生成器函数
function * gen(arg){
  console.log(arg) // 'gen执行时的参数'
  // 创建变量,接收next方法内的实参
  let next2Arg = yield 1
  console.log(next2Arg) // '第2次next的参数'
  let next3Arg = yield 2
  console.log(next3Arg) // '第3次next的参数'
  let next4Arg = yield 3
  console.log(next4Arg) // '第4次next的参数'
}

let iterator = gen('gen执行时的参数')
iterator.next()
// 第2次next方法开始可以传入实参
// 该实参由当前next方法所执行语句的前一个yield所接受
iterator.next('第2次next的参数')
iterator.next('第3次next的参数')
iterator.next('第4次next的参数')

- 生成器函数-模拟请求数据

- 代码例:

// 请求用户数据
function getUsers() {
  setTimeout(()=>{
    let data = '用户数据'
    // 传入用户数据,执行下个next
    iterator.next(data)
  },1000)
}

// 请求订单数据
function getOrders() {
  setTimeout(()=>{
    console.log(users) // '用户数据'
    let data = '订单数据'
    // 传入订单数据,执行下个next
    iterator.next(data)
  },1000)
}

// 请求商品数据
function getGoods() {
  setTimeout(()=>{
    console.log(orders) // '订单数据'
    let data = '商品数据'
    // 传入商品数据,执行下个next
    iterator.next(data)
  },1000)
}

// 创建生成器函数
function * gen() {
  // users 用户数据实参
  let users = yield getUsers()
  // orders 订单数据实参
  let orders = yield getOrders()
  // goods 商品数据实参
  let goods = yield getGoods()
}

// 创建迭代器对象并调用next
let iterator = gen()
iterator.next()


- Recorded by Scorpio_sky@2021-01-17

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值