1. 概述
- ECMAScript 是 JavaScript 的标准化规范
- ECMAScript 只提供了基本语法
- JavaScript 是 ECMAScript 的扩展语言
- 浏览器环境的 JavaScript = ECMAScript + DOM + BOM
- node 环境的 JavaScript = ECMAScript + fs + net + etc.
- ES2015 相比较 ES5.1 的变化
- 解决原有语法上的一些问题或不足
- 对原有语法进行增强
- 全新的对象,全新的方法,全新的功能
- 全新的数据类型和数据结构
2. 作用域
- 作用域:某个成员能够起作用的范围
- ES2015 之前只有两种作用域,分别是全局作用域和函数作用域
- ES2015 中新增了块级作用域
- 在块级作用域内定义的成员外部无法访问
- 全局作用域
- var 关键字声明的成员在全局作用域,具有变量提升的特性
- 块级作用域
- 花括号形成的块的作用域
- let 和 const 都可以声明块级作用域成员,没有变量提升的特性,使用闭包的原理将变量封锁在一个独立的块内
- const 声明常量,在 let 的基础上多了一个只读特性,一经声明,必须赋值,声明的成员不能修改
- 注:不允许修改指的是不允许指向另一个新的内存地址(即引用)
3. 数组的解构
-
声明解构语法,变量必须对应所对应的值
const arr = [100, 200, 300] const [foo, bar, baz] = arr console.log(foo, bar, baz) // 100, 200, 300 -
... 表示把剩余数据存放到变量中(以数组方式返回),只能在最后一个成员使用
const arr = [100, 200, 300] const [foo, ...reset] = arr console.log(reset) // [200, 300] -
声明的变量少于数组的长度,会按照从左到右的顺序赋值
const arr = [100, 200, 300] const [foo] = arr console.log(foo) // 100 -
声明的变量大于数组的长度,多出来的变量为 undefined
const arr = [100, 200, 300] const [foo, bar, baz, more] = arr console.log(more) // undefined -
可以给变量设置默认值
const arr = [100, 200, 300] const [foo, bar, baz, more = 'default'] = arr console.log(more) // default
4. 对象的解构
-
解构的变量要对应对象中的 key
const obj = { name: 'kjy', age: 24 } const { name } = obj console.log(name) // kjy -
重命名变量
const obj = { name: 'kjy', age: 24 } const name = 'kxy' const { name: myName } = obj console.log(myName) // kjy -
如果成员没有匹配到,则变量的值为 undefined
const obj = { name: 'kjy', age: 24 } const { sex } = obj console.log(sex) // undefined -
设置默认值
const obj = { name: 'kjy', age: 24 } const { sex = '男' } = obj console.log(sex) // 男
5. 模板字符串
-
支持换行
-
支持通过插值表达式(${ 变量/JavaScript 语句 })的方式嵌入数据
-
用法
const name = 'kjy' const str = `My name is ${ name }` console.log(str) // My name is kjy -
带标签的模板字符串
-
作用:对模板字符串进行加工,标签函数的返回值就是模板子字符串接收的值
const name = 'kjy' const gender = true function myTagFn(strings, name, gender) { console.log(strings) // ['My name is ', ', sex is '] gender = gender ? '男' : '女' retunr strings[0] + name strings[1] + gender } const result = myTagFn`My name is ${ name },gender is ${ gender }` console.log(result) // My name is kjy, gender is 男
-
6. 字符串的扩展方法
-
inclueds() 包含某个字符
-
startsWith() 以某个字符开始
-
endsWith() 以某个字符结束
const message = 'Error: foo is not defined' console.log(message.inclueds('Error')) // true console.log(message.startsWith('Error')) // true console.log('message.endsWith('defined')') // true
7. 参数默认值
-
当没有传入参数或者 undefined 时使用默认值
function foo(enable){ console.log(enable) } foo(true) // true function foo(enable = false){ console.log(enable) } foo() // false -
注:带有默认值的参数一定要放到参数列表最后
8. ... 操作符
-
使用 ... 操作符可以表示剩余操作符,以数组的形式接收传入参数
function foo(...args){ console.log(args) // [1, 2, 3] } foo(1, 2, 3) -
注:... 操作符只能出现在形参的最后一位,只可以使用一次
-
使用 ... 操作符可以展开数组
const arr = ['foo', 'bar', 'baz'] console.log(...arr) // foo bar baz
9. 箭头函数
-
传统的函数
function foo(number) { return number + 1 } console.log(foo(100)) // 101 -
箭头函数
const foo = number => number + 1 console.log(foo(100)) // 101 const inc = (n, m) => { return n + 1 } console.log(inc(100)) // 101 const arr = [1, 2, 3, 4, 5] const arr1 = arr.filter(item => item % 2 === 0) console.log(arr1) // [2, 4]-
箭头函数不会改变 this 指向,箭头函数中的 this 永远指向当前作用域中的 this
const person = { name: 'kjy', sayHi: function (){ console.log(`hi my name is ${this.name}`) // my name is kjy }, sayHi: () => { console.log(`hi my name is ${this.name}`) // my name is undefined } }
-
10. 对象字面量的增强
const bar = '345'
const obj = {
foo: 123,
bar,
method1 () {
console.log('method1') // method1
console.log(this) // { foo: '123', bar: '345', method1: Function: method1 }
},
// 动态属性
[Math.random()]: 123
}
11. Object 扩展方法
-
Object.assign()
-
Object.assign() 可以将多个源对象中的属性复制到一个目标对象中
-
如果有相同的属性,源对象的属性会覆盖掉目标对象中的属性
const source1 = { a: 123, b: 456 } const target = { a: 789, c: 101112 } const result = Object.assign(target, source1) console.log(target) // { a: 123, c: 101112, b: 456 } console.log(result === target) // true
-
-
Object.is()
-
Object.is() 可以判断两个值是否相等
console.log(+0 === -0) // true console.log(Object.is(+0, -0)) // false console.log(NaN === NaN) // false console.log(Object.is(NaN, NaN)) // true
-
12. Proxy 代理对象
-
很容易监听到属性的变更
-
Proxy 是以非侵入的方式监管了整个对象的读写
const person = { name: 'kjy', age: 24 } const personProxy = new Proxy(person, { // 监视获取属性 // target 代理目标对象 // 操作属性 get (target, property) { console.log(target, property) // { name: 'kjy', age: 24 } name return target[property] }, // 监视设置属性 // target 代理目标对象 // property 操作属性 // value 设置的值 set (target, property, value) { target[property] = value }, // 删除目标对象属性时自动执行 deleteProperty (target, property) { delete target[property] } }) console.log(personProxy.name) // kjy
13. reflect
-
统一的对象操作 API
-
Reflect 属于一个静态类,不能通过 new 的方式构建一个实例对象
-
Reflect 内部封装了一系列对对象的底层操作
-
Reflect 成员方法就是 Proxy 处理对象的默认实现
const obj = { foo: '123', bar: '456' } const objProxy = new Proxy(obj, { get (target, property) { return Reflect.get(target, property) } }) console.log(objProxy.foo) // 123
14. Promise
- 解决了传统异步编程中回调函数嵌套过深的问题
15. class 类
-
之前定义类型的方式
-
通过构造函数的方式来定义类型
function Person(name){ this.name = name } Person.prototype.say = function () { console.log(`hi,my name is ${this.name}`) }
-
-
ES2015 之后定义类型的方式
-
通过 class 关键字定义类型
class Person{ constructor(name){ this.name = name } // 实例方法 say (){ console.log(`hi,my name is ${this.name}`) } // 静态方法 static create(name){ return new Person(name) } } // 类的继承 class Student extends Person { // Student 中 拥有 Person 的所有成员 constructor(name, number){ // 调用 super 相当于调用了父类的构造函数 super() this.number = number } } const p = new Person('kjy') p.say() // hi,my name is kjy
-
16. Set 数据结构
-
Set 中的成员不允许重复
const s = new Set() // add 方法返回实例对象本身,所以可以链式调用 // 如果添加重复值,重复的值会被忽略掉 s.add(1).add(2).add(3).add(1) console.log(s) // Set {1, 2, 3} // 获取 Set 实例中的长度 s.size // 3 // 判断集合中是否包含指定的值 s.has(100) // false // 删除集合中指定的值 s.delete(3) // true // 清除实例对象 s.clear() // 利用 Set 给数组去重 const arr = [1, 2, 3, 4, 1, 2] // Set 构造函数接收一个数组 const result = new Set(arr) console.log(result) Set {1, 2, 3, 4}
17. Map
-
键值对集合,用来映射两个任意类型之间的对应关系
const m = new Map() const tom = { name: 'tom' } // 通过 set 方法设置键值对 m.set(tom, 90) console.log(m) // Map { { name: 'tome' => 90 } } // 通过 get 方法获取某一个键的值 m.get(tom) // 90 // 通过 has 方法判断某个键是否存在 m.has(tom) // true // 通过 delete 方法删除某个键 m.delete(tom) // true // 通过 clear 方法情况 Map 集合 m.clear() // true
18. Symbol
- 表示一个独一无二的值
- Symbol.for() 接收一个字符串作为参数,相同的参数,Symbol 值也是相同的
19. for of 循环
-
之后会作为所有数据结构的统一方式
const arr = [100, 200, 300, 400, 500] // for of 循环拿到的是数组中元素,而不是对应的下标 for (const item of arr){ console.log(item) // 100 200 300 400 500 }
20. 可迭代接口 Iterable
-
实现了 Iterable 接口就是 for of 的前提
-
对外提供统一遍历接口
const s = new Set(['foo', 'bar', 'baz']) const iterator = s[Symbol.iterator]() console.log(iterator) // { value: 'foo', done: false } -
实现可迭代接口
const obj = { name: 'kjy', age: 24, store: ['foo', 'bar', 'baz'], // 可迭代接口 iterable [Symnol.iterator]: function(){ let index = 0 const self = this // 迭代器对象 iterator return { next: function (){ // 迭代结果接口 iterationResult const result = { value: self.store[index], done: index++ >= store.length } return result } } } }
21. 生成器函数 Generator
-
避免异步编程中回调嵌套过深,提供更好的异步编程解决方案
-
生成器函数返回一个生成器对象,生成器对象中存在用于迭代的 next 方法
function * foo(){ console.log('kjy') return 100 } const result = foo() console.log(result) // Object [Generator] {} console.log(result.next()) // { value: 100, done: true } -
yield 的使用
- yield 关键词用于暂停函数的执行,yield 后边的值作为 next 的结果返回
function * foo(){ console.log('11111') yield 100 console.log('22222') yield 200 console.log('33333') yield 300 } const result = foo() console.log(result.next()) // 11111 { value: 100, done: false } console.log(result.next()) // 22222 { value: 200, done: false } console.log(result.next()) // 33333 { value: 300, done: false }