ES6学习笔记(五)【解构赋值,Iterator】

简介

在很多流行的编程语言里,都有解构赋值的概念,比如PerlPython

ES6中也加入了类似的赋值语句,比以前的赋值操作更灵活,更快捷

正文

数组的解构赋值很好理解,就是按照对应位置,对变量赋值:

let [a, b, c] = [1, 2, 3]

相当于

let a = 1
let b = 2
let c = 3

支持数组嵌套,也支持等号两边结构不同的情况

如果变量对应不上值,这个变量就是undefined,如果一个值对应不到变量,那这个值被忽略

[a, b, c] = [1, 2]
// a,b为1,2   c由于匹配不到为undefined
[a, b] = [1, 2, 3]
// a,b为1,2   3由于没有变量接收被忽略

基于解构赋值,函数也可以有多个返回值了:

function tuple() {
  return [1, 2]
}

let [first, second] = tuple()

解构赋值允许指定默认值,也允许使用rest参数(...)来接收不确定个数的参数:

let [firstName = "John", lastName = "Doe"] = []

let [a, b, ...rest] = [1, 2, 3, 4, 5]
a    // 1
b    // 2 
rest // [3, 4, 5]

与函数的rest参数一样,rest后面不允许再有其他参数了

对象的解构赋值与数组类似,只有在属性名对应相同的情况下,右侧属性的值会被赋值给左侧对应属性的值

let {firstName: name, lastName} = {firstName: "John", lastName: "Doe"}

name      // "John"
lastName  // "Doe"
firstName // Uncaught ReferenceError: firstName is not defined

注意被赋值的是同名属性的值,这里是name 而不是firseName

lastName被赋值成功是因为这是变量的简洁表示法,忘记了的回去看对象一节

其实数组可以看做属性名都是自然数的对象:

let {"0": a, "1": b} = {"0": 1, "1": 2}

a     // 1
b     // 2

这样看起来会更好的理解对象的解构赋值,实际上行为与数组的解构赋值是一致的

思考

这部分内容希望你都可以手动敲一遍,独立思考

试着用解构赋值去交换两个变量的值

如果不使用解构赋值,如何交换两个变量的值呢?


let [a = 1] = [undefined]

let [b = 1] = [null]

上面代码中的a, b分别是什么?试着自己解释这个结果


let [x = y, y = 1] = []

上面代码的结果是什么? 为什么?


ES6中新增了一种遍历语法:for (... of ...) 来支持所有可遍历的数据结构

for-of 是基于iterator这个通用接口实现的

正文

在ES6以前,我们想遍历一个数组一般有三种方式:

  • for 循环
  • for ... in 语句
  • Array.prototype.forEach 方法

三种方式都有不同程度的缺陷

for循环写法繁琐,需要指定循环次数不超过数组长度,否则就会有对应的报错

for ... in 语句遍历出的是键值,需要做一些转换才能拿到数据,而且遍历是无序的

forEach 方法是个不错的方式,不过它不能中途使用break跳出循环,也不能return终止外层函数

基于这些缺陷,ES6新增了 for ... of 的语法,用于遍历数组,对象,字符串,或者是SetMap等数据结构

for ... of 遍历依赖 iterator 接口,只有部署了 iterator 接口的数据类型才可以被遍历

iterator 接口是这些数据结构上的一个属性:Symbol.iterator,它是一个函数

let iterator = [1, 2, 3][Symbol.iterator]()

iterator    //  Array Iterator {}
iterator.next()
// {value: 1, done: false}
iterator.next()
// {value: 2, done: false}
iterator.next()
// {value: 3, done: false}
iterator.next()
// {value: undefined, done: true}

Symbol.iterator显然是一个Symbol类型值,在Symbol章节介绍过,必须使用方括号访问

调用数组上的 Symbol.iterator 方法,即可返回一个iterator遍历器对象

这个 iterator 对象上只有一个常用方法 next ,每次调用 next 即可返回一个对象

返回的对象有两个属性,value :当前遍历的值, done :是否遍历完毕

这里必须说明一下为什么这个遍历器的属性名是一个很绕的Symbol类型

其实最开始是打算叫做 iterator() 的 ,可是考虑到已有的代码中,可能已经有人用这个名字命名了一些属性

ES6如果直接使用这个名字会造成兼容性问题,无奈之下只能使用绝对不可能重复的 [Symbol.iterator]()

for…of 语句会在内部直接调用遍历对象上的 Symbol.iterator 方法

并且每次循环中自动调用返回值的next方法,然后将next方法返回值的value属性值赋值给每次的循环变量

for (let a of arr){
  console.log(a)
}
//  1  2  3

正常情况下我们不会手动使用next方法去一个一个的拿到值

而是使用 for … of 方便的遍历所有具有 Symbol.iterator 属性的对象

思考

这部分内容希望你都可以手动敲一遍,独立思考

let map = new Map([
  ['a', '1'],
  ['b', '2']
])

for (let a of map){
  console.log(a)
}

上面代码的输出结果会是什么?

如果想要每次只输出map中每一项对应的值,应该怎么改写?


试着根据上面描述的for ... of实现方法,自己动手实现一个具有for ... of功能的function

接收一个可遍历对象,并向命令行依次输出遍历结果

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值