ES就ECMAScript,ECMA标准化组织发布的一项脚本语言标准化规范
ES6是一个泛指,泛指ES2015及其之后的版本
一、let关键字是用来定义变量的
-
let定义的变量有块级作用域,而用var定义的变量是木有块级作用域,块级作用域就是一对花括号
if (true) {
var a = 10
}
console.log(a) // 10if (true) { let a = 10 } console.log(a) // 报错:a is not defined // ------------ for (var i = 0; i < 10; i ++) { ... } console.log(i) // 10 for (let i = 0; i < 10; i ++) { ... } console.log(i) // 报错:i is not defined
-
没有变量提升
console.log(a) // 报错:a is not defined
let a = 10 -
暂时性死区(与世隔绝,只认所在的块级作用域)
var num = 10
if (true) {
console.log(num) // 报错:ReferenceError: can’t access lexical declaration `num’ before initialization
let num = 100
} -
不能重复定义
let a = 10
let a = 100 // SyntaxError: redeclaration of let a
二、const关键字:
- 有块级作用域
- 不可重复定义
- 没有变量提升
- 也有暂时性死区
- 不可重新给常量赋值(变量在栈内存中的值)
- 复杂数据类型内部的值可以改
- 定义时必须赋值
三、var、let、const的区别:
区别 | var | let | const |
---|---|---|---|
作用域 | 函数(局部) | 块级 | 块级 |
是否存在变量提升 | 存在 | 不存在 | 不存在 |
是否可重新赋值 | 可以 | 可以 | 不可以 |
是否可重复定义 | 可以 | 不可以 | 不可以 |
定义时是否必须赋值 | 否 | 否 | 是 |
是否存在暂时性死区 | 否 | 是 | 是 |
全局作用域定义时是否会挂载到window上 | 是 | 否 | 否 |
补充说明:优先用const,因为效率要高一丢丢,如果后续发现需要重新赋值,再来改成let
四、数组解构赋值:
const arr = [1, 2, 3]
const a = arr[0]
const b = arr[1]
const c = arr[2]
// -------- 上面的代码等价于下面的代码 ---------
const arr = [1, 2, 3]
const [a, b, c] = arr
// ------- 如果解构时,个数比数组中的元素多,那么只能解构出对应的数据,解构不成功的是undefined,如下范例: -----
const arr = [1, 2, 3]
const [a, b, c, d, e] = arr // a = 1, b = 2, c = 3, d = undefined, e = undefined
// ------- 如果解构时,个数比数组中的元素少,那么是可以正常解构的,如下范例: -----
const arr = [1, 2, 3]
const [a, b] = arr // a = 1, b = 2
五、对象解构:
const user = { name: 'zs', age: 18, sex: '男' }
const name = user.name // user['name'], var key = 'name', user[key]
const age = user.age
const sex = user.sex
// --------- 下面的代码和上面等价 --------
const user = { name: 'zs', age: 18, sex: '男' }
const { name, age, sex } = user
这里注意:变量名必须和对象中的键名一致,否则解构不出来,如果想要改名字,范例如下:
const user = { name: 'zs', age: 18, sex: '男' }
const { name: myName, age: myAge } = user // 可以只解构一部分键值对
在函数的形参上也可以使用对象结构,如下:
function sayHi(user) {
console.log(`hi, my name is ${user.name}, age is ${user.age}, sex is ${user.sex}`)
}
const zs = { name: 'zs', age: 18, sex: '男' }
sayHi(zs)
// ------ 下面的代码和上面等价
function sayHi({ name: myName, age, sex }) {
console.log(`hi, my name is ${myName}, age is ${age}, sex is ${sex}`)
}
const zs = { name: 'zs', age: 18, sex: '男' }
sayHi(zs)
六、箭头函数(函数的语法糖)
-
基本语法:
function fn () {}
// 上下代码等价
const fn = () => {} -
如果函数体只有一句代码,可以省略 return 和 花括号(省略掉后,这句代码的结果会作为函数的返回值):
const fn = (n1, n2) => {
return n1 + n2
}
// 上下代码等价
const fn = (n1, n2) => n1 + n2// ------------- const fn = (n1, n2) => { console.log(n1, n2) } // 上下代码唯一的区别就返回值的区别 // 上面的代码返回值是undefined // 下面的代码返回值是console.log函数的返回值 const fn = (n1, n2) => console.log(n1, n2)
-
如果形参只有一个,那么小括号也可以省略(如果没有参数或有多个参数,则小括号不能省)
const fn = (v) => {
return v * v
}
// 上下代码等价
const fn = v => v * v -
箭头函数中的this指向该箭头函数定义时所在位置的this(最重要),如下代码:
范例1:
const obj = { name: ‘张三’}
function fn () {
console.log(this) // { name: ‘张三’}
return () => {
console.log(this) // { name: ‘张三’}
}
}
const resFn = fn.call(obj);
resFn();
范例2:
var age = ‘100岁’
const obj = {
name: ‘zs’,
age: 18,
sayHi: () => {
console.log(this.age) // 100岁
}
}
obj.sayHi() -
箭头函数木有arguments变量(是一个伪数组),我们可以用剩余参数来代替(是一个真正的数组),并且效果更好:
const sum = (…args) => {
let total = 0
args.forEach((v) => {
total += v
})
return total
}sum(1, 2) sum(1, 2, 3, 4, 5)
补充说明:所谓伪数组就意味着不能调用数组相关的API方法,如:forEach、some、push…
七、剩余参数和解构配合使用:
数组:
const arr = ['red', 'green', 'blue', 'yellow', 'white']
const [s1, ...s2] = arr
// const [...s1, s2] = arr // 注意:这是会报错的,剩余参数只能写在最后
console.log(s1) // 'red'
console.log(s2) // ['green', 'blue', 'yellow', 'white']
对象:
const obj = { name: 'zs', age: 18, sex: '男' }
const { name, ...newObj } = obj
console.log(name) // 'zs'
console.log(newObj) // { age: 18, sex: '男' }
八、扩展运算符
可以将数组中的元素展开成参数序列,如下范例:
const arr = [1, 2, 3]
// ...arr // 1, 2, 3
console.log(...arr)
// console.log(1, 2, 3)
// -----------------------
fn(...arr) // fn(1, 2, 3)
const newArr = [0, ...arr, 4, 5, 6] // const newArr = [0, 1, 2, 3, 4, 5, 6]
// --------------
const newArr = []
arr.forEach(v => {
newArr.push(v)
})
// 上下代码等价
const newArr = [...arr]
可以将对象中的键值对展开成键值对序列,如下范例:
var obj = { name: 'zs', age: 18 }
// ...obj // name: 'zs', age: 18
var newObj = { id: 1, ...obj, sex: '男' }
// var newObj = { id: 1, name: 'zs', age: 18, sex: '男' }
注意:扩展运算符只能将带有Symbol.iterator属性的伪数组转换成真正的数组
静态方法:直接用构造函数调用的方法
动态方法:用实例调用的方法
Array.from可以把一个伪数组转换成真正的数组,不需要有Symbol.iterator属性
九、数组实例扩展的方法:
- find:找数组中第一个符合条件的元素并返回,内部有循环机制,只要return true,则返回当前循环项,立即终止循环
const arr = [ { id: 1, name: ‘zs’ }, { id: 2, name: ‘ls’ } ]
const obj = arr.find((v, i) => {
/*
if (v.id === 2) {
return true
}
*/
return v.id === 2
})
// obj = { id: 2, name: ‘ls’ } - findIndex:和find差不多,只不过返回的索引,不是元素
const arr = [10, 20, 50]
const index = arr.findIndex(v => v > 15)
console.log(index) // 1 - includes:看数组中是否包含某个元素,返回值是布尔型,true:包含,false:不包含
const arr = [‘a’, ‘b’, ‘c’]
const result1 = arr.includes(‘b’)
console.log(result1) // true
const result2 = arr.includes(‘e’)
console.log(result2) // false- 如果传递一个函数,那么是找数组中是否包含这个函数,内部并没有循环机制
- 如果是复杂数据类型,那么找的是内存地址,如下范例:
const obj = { name: ‘zs’ }
const arr = [‘a’, ‘b’, ‘c’, obj]
const result1 = arr.includes(obj) // true
const result2 = arr.includes({ name: ‘zs’ }) // false
十、模板字符串:字符串的语法糖
- 可以写一些简单JS表达式(包括:变量、函数、算数运算、逻辑运算、三元表达式)通过${ 表达式 }
- 可以换行
字符串实例方法扩展:
- str.startsWith(prefixStr):判断str这个字符串是否以prefixStr开头,类似:/^prefixStr/.test(str)
- str.endsWith(suffixStr):判断str这个字符串是否以suffixStr结尾,类似:/suffixStr$/.test(str)
- str.repeat(n):可以将str这个字符串重复n次并返回
十一、Set数据结构:ES6新增的数据结构,类似数组,但是内部不会有重复的元素(值、内存地址),并且是一个无序的数据结构,木有索引号
- 可以通过构造函数来创建Set数据结构的实例:new Set()或new Set([ 1, 2, 3 ])
- 可以通过size属性获取Set数据结构实例的长度
- 实例方法:
- add:添加,返回值是数据结构本身,可以链式调用
- delete:删除,返回值是布尔值,true:删除成功,false:删除失败
- has:是否存在,返回值是布尔值,true:存在,false:不存在
- clear:清空,木有返回值
- forEach:遍历元素,类似数组,但是木有索引
补充说明,我们可以先将其转换成数组([…someSet]),再来调用数组上强大的API方法操作数据