ES6新增的部分语法

1.let和const

let和const的出现是为了弥补var,其中let是声明变量,const是声明常量,这两个变量主要解决了以下两个问题

(1)变量提升

var变量会发生‘变量提升’现象,即变量在声明之前使用,值为undefined

console.log('testVar:', testVar) // testVar: undefined
var testVar = 17

console.log('testLet', testLet) // 报错ReferencEerror
let testLet = 16

当代码复杂度越来越大时,变量提升问题容易造成混乱,使得代码可读性差,不利于迭代和维护

(2)新增块级作用域

所谓块级作用域,即规定一个变量(常量)仅在所声明的区域里面有效,一般这区域由{}隔开。习惯c或java的朋友(包括我自己)会习惯性默认这个概念,但在JS的var声明的变量中并非如此

function f() {
  var n = 7
  if (true) {
    var n = 10
  }
  console.log('n:', n) // n: 10
}

f()

以上代码中,可看到n最终输出10,说明if花括号里面的变量n只是重新赋值而不是重新声明,用var声明的变量不存在块级作用域 ,我们把var转换成let

function f() {
  let n = 7
  if (true) {
    let n = 10
  }
  console.log('n:', n) // n: 7
}

f()

会发现在if大括号里面声明的变量n不会作用到外面的区域,即存在块级作用域。另外在一个块级作用域中,不允许重复声明一个变量

2.解构赋值

解构赋值是一种更简便的赋值方式。按照一定的模式在数组或对象中提取值(提取过程即解构),然后对变量进行赋值。

(1)数组的解构赋值

在以前的代码中,为变量赋值只能一一指定值,如

let x = 1
let y = 2
let z = 3

在ES6中允许这样使用

let [x, y, z] = [1, 2, 3]
console.log(x, y, z) //1 2 3

x,y,z正常拿到对应的值

以下还有几种常见情况

// 1.用,隔开能准确提取相应的值
let [, , JS] = [1, 2, 'cool']
console.log('JS:', JS) // JS: cool   

// 2.存在解构不成功的情况,赋值默认为undefined
let [x, y, z] = [1, 2]
console.log('x:', x) // x: 1
console.log('y:', y) // y: 2
console.log('z:', z) // z: undefined  等式右边的模式少一个元素(也可看作等式左边的模式多了一个元素),此时z的值为undefined

// 3.默认赋值
let [x = 1] = [1] 
console.log(x) // 1

let [x = 1, y = x] = []
console.log(x, y) // 1 1

let [x = 1, y = x] = [1]
console.log(x, y) // 1 1

let [x = 1, y = x] = [2]
console.log(x, y) // 2 2 

let [x = 1, y = x] = [1, 2]
console.log(x, y) // 1 2 

// 注:默认值不能是未声明的值
let [x, y = z] = [] 
console.log(x, y) // 报错ReferenceError: z is not defined

(2)对象的解构赋值

let {y, x} = {x:'aaa', y:'bbb'}
console.log('x:', x) // x: aaa
console.log('y:', y) // y: bbb

以上代码是对象的解构赋值的基本用法,可看到赋值是无序的,机制会自动寻找同名属性。以下聊聊解构赋值的机制:

let {x:foo, y:bar} = {x:'aaa', y:'bbb'} 
console.log(foo, bar) // aaa bbb
// 从上面的输出结果来看,解构赋值成功给变量foo和bar赋值,可以尝试输出x,y,系统将会报错
// 由此可看出对象解构赋值的内部机制是找到等式左右边的同名属性,然后再赋值给相应的变量
/* 
所以
let {x, y} = {x:'aaa', y:'bbb'} 
其实是
let {x:x, y:y} = {x:'aaa', y:'bbb'}
*/

对象解构赋值的机制是找到等式左右两边的同名属性,然后再赋值给相应的变量

 下面是一些更为复杂的例子:

let obj = {};
let arr = [];
({x:obj.prop, y:arr[0]} = {x:'aaa', y:true});
console.log(obj) // { prop: 'aaa' }
console.log(arr) // [ true ]

 对象的解构赋值也可以设置默认变量:

let {x = 3, y = 4} = {}
console.log(x, y) // 3 4

3.扩展运算符和rest参数

rest参数和扩展运算符都是ES6的新特性,rest参数的形式 ...(变量名),前面的...(3个点)即是扩展运算符

(1)rest参数:用于获取函数多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入其中。

function add(...args) {
  console.log(args) // [1,2,3]
  let sum = 0
  for (let i of args) {
    sum += i
  }  
  return sum
}

console.log(add(1,2,3)) // 6

以上代码中,给add函数传递3个参数,rest参数将参数列表转化成数组存储到args中,最终成功求和

function add(x, y, ...args) {
  console.log(args) // [3,4,5]
  let sum = 0
  for (let i of args) {
    sum += i
  }  
  return sum
}

console.log(add(1,2,3,4,5)) // 12

以上代码中,args仅获取后3个参数,x、y分别获取参数1、2

(2)数组的扩展运算符:如同rest的逆运算,将一个数组转为用逗号分隔开的参数序列

 console.log(...[1,2,3])  // 1 2 3

以上代码中将数组转化成参数数列

function add(x, y) {
  console.log(x, y) // 1 2
  return x+y
}
const num = [1,2]
console.log(add(...num)) // 3

以上代码中扩展运算符将num数组转化成参数序列传值给add函数

以下为数组扩展运算符的一些应用

// 1.合并数组
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
arr1 = [...arr1, ...arr2]
console.log(arr1) // [ 1, 2, 3, 4, 5, 6 ]

// 2.用于解构赋值
let [x, y, ...arg] = [1,2,3,4,5,6]
console.log(x) // 1
console.log(y) // 2
console.log(arg) // [ 3, 4, 5, 6 ]

// 3.函数传参如上例

(2)对象的扩展运算符:形式...(对象名)

// 1.用于结构赋值  注:解构赋值必须是最后一个参数,否则会报错
let {x, y, ...z} = {
  x: 1,
  y: 2,
  a: 3,
  b: 4
}
console.log(z) // { a: 3, b: 4 }


// 2.用于参数对象的所有可遍历属性,并将其复制到当前对象中,类似于合并对象
let x = {a:1, b:2}
let y = {c:3, d:4}
let z = {...x, ...y}
console.log(z) // { a: 1, b: 2, c: 3, d: 4 }

4.数据结构Set和Map

Set,Map都是ES6新增的数据结构

Set:它类似于数组,但是成员的值都是唯一的

(1)Set可接受一个数组(或实现iterator接口的数据结构)作为参数,用于初始化

let set = new Set([1,2,3,3])
console.log(set) // Set { 1, 2, 3 }

(2)Set实例的属性和方法

  • size属性:返回成员的个数
  • add(value):添加一个成员,返回set本身
  • delete(value):删除一个成员,返回布尔值
  • has(value):判断是否存在某个成员,返回布尔值
  • clear():清除所有成员,没有布尔值
let set = new Set([1,2,3])
set.add(4).add(7).add(5)
console.log(set) // Set { 1, 2, 3, 4, 7, 5 }
console.log(set.has(2)) // true
console.log(set.delete(2)) // true
console.log(set.has(2)) // false
set.clear()
console.log(set) // Set {}

Map:它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键(在普通的object中,只用用字符串作为键)

(1)Map可接受一个数组作为参数,该数组的成员是一个个表示键值对的数组

let map = new Map([
  ['name', 'jack'],
  ['old', '17']
])
console.log(map) // Map { 'name' => 'jack', 'old' => '17' }

(2)Map实例的属性和方法

  • size属性:返回成员的个数
  • set(key, value):设置key所对应的整个键值,然后返回整个Map结构,若key已经有值,则键值会被更新
  • get(key):获取key对应的键值,若找不到key,返回undefined
  • has(key):判断某个键是否存在,返回布尔值
  • delete(key):删除某个键,返回布尔值
  • clear():清除所有成员,没有返回值
let map = new Map([
  ['name', 'jack'],
  ['old', '17']
])

console.log(map) // Map { 'name' => 'jack', 'old' => '17' }
console.log(map.size) // 2
console.log(map.set('old', 18)) // Map { 'name' => 'jack', 'old' => 18 }
console.log(map.get('name')) // jack
console.log(map.has('name')) // true
console.log(map.delete('old')) // true
console.log(map) // Map { 'name' => 'jack' }
map.clear()
console.log(map) // Map {}

5.for...of 循环

ES6新增循环for...of,作为遍历所有数据结构的统一方法,一个数据结构只要实现了iterator接口,就可以用for...of循环遍历它的成员

(1)对数组的遍历

for (let i of [1,2,4,5]) {
  console.log(i) // 1 2 4 5
}

(2)对Set和Map的遍历

let set = new Set([1,2,3,4])
for (let i of [1,2,4,5]) {
  console.log(i) // 1 2 4 5
}

let map = new Map([
  ['name', 'jack'],
  ['old', '17']
])
for (let [key, value] of map) {
  console.log(key, value) 
}

(3)对对象的遍历

对于普通的对象,for...of循环不能直接使用,因为对象没有部署iterator接口

let obj = {
  'name': 'jack',
  'old': '17'
}
for (let i of obj) { // 报错 TypeError: obj is not iterable
  console.log(i) 
}

可以使用对象的keys(),values(),entries()方法用于遍历

let obj = {
  'name': 'jack',
  'old': '17'
}
for (let i of Object.keys(obj)) { 
  console.log(i) // name old
}

for (let [key, value] of Object.entries(obj)) {
  console.log(key, ': ', value) 
}

/*
name :  jack
old :  17
*/

(4)for...of与forEach、for...in循环的比较

forEach:在forEach循环中,break命令或return命令都无效,循环难以中途退出

for...in:此循环专门为遍历对象而设计,每次遍历获取当前对象的key值,通过key可以拿到value,若用于遍历数组,会以字符串作为键名(将数组作为对象)输出,‘0’、‘1’、‘2’...

// for...in 遍历对象
let data = {
  '123': 'abc',
  '456': 'def'
}

for (let item in data) {
  console.log(item, data[item])
}

/**
 *  123 abc
 *  456 def
 * 
 */



// for...in 遍历数组
let arr = ['abc', 'def']
for (let i in arr) {
  console.log(i , typeof(i))
}

/*
0 string
1 string
*/

for...of语法与for...in一样简洁,可以在循环体内使用break、continue以达到中途退出,提供了遍历所有数据结构的统一操作接口

for...in循环适用于遍历对象,for...of用于遍历实现了iterator接口的数据类型

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值