ES6
全称ECMAScript 6.0
,部分浏览器不支持ES6,在应用程序的构建过程中需要使用babel
将ES6
转换为ES5
. es6新特性:默认参数
、箭头函数
、模块化
、Proxy
、Generator构造器函数
、Promise
等
函数的扩展
默认参数 函数体内不能再使用
let const
声明形参 默认参数必须放在最后面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function fn(a=10, b=20){
console.log(a, b)
}
fn() // 10 20
fn(6) // 6 20
fn(8, 9) // 8 9
// 间隔传递默认参数可以使用 undefiend代替
function f(x, y=7, z=43){
return x + y + z
}
console.log(f(1, undefined, 20)) // 28
// 函数体内不能再使用`let const`声明形参
function fn(a){
let a = 3; // Identifier 'a' has already been declared
}作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域,初始化结束,作用域就会消失,不设置默认值是不会出现的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25let x = 1
function fn (x, y = x) {
console.log(y)
}
// 参数y设置默认值等于x,调用fn形成单独的作用域,在作用域内,x指向第一个参数,而不是全局的变量x
fn(2) // 2
let a = 1
function fn(b = a) {
let a = 2
console.log(b)
}
/* 函数fn调用时,参数b=a形成单独的作用域,在作用域内,变量a没有定义,
指向外层的全局变量a,函数体内的局部变量a不会影响默认值变量a */
fn() // 1
var x = 1
/* 函数foo的默认参数形成单独的作用域,在此作用域内,首先声明变量x和y,匿名函数y内部的变量x指向此作用
域内的第一个参数x,函数foo内部的变量x也指向了第一个参数x,与匿名函数内部的x是一致的,执行y()后,将参
数x修改为2,外部的全局变量依然不受影响,若将foo内部的x=3修改为 var x=3,则输出的是3 */
function foo (x, y = function () { x = 2}) {
x = 3
y()
console.log(x)
}
foo() // 2
console.log(x) // 1函数的rest参数(…参数名) 剩余参数
Spread Operator扩展运算符(…实参) 和 Rest Parameter(…形参) 是形似但相反意义的操作符,Rest Parameter 是把不定的参数“收敛”到数组,而 Spread Operator 是把固定的数组内容“打散”到对应的参数
用于获取函数的多余参数,这样就不需要使用arguments
对象了rest
参数搭配的变量是一个数组,该变量会把多余的参数放入数组中.后边不能再有其他参数,否则会报错1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25function sum(...arr) {
console.log(arr) // [1, 2, 3, 4, 5]
let res = 0
arr.map((item) => {
res+=item
})
console.log(res)
}
sum(1, 2, 3, 4, 5) // 15
function sum1(arg, ...arr) {
console.log(arr) // [2, 3, 4, 5]
let res = arg
arr.map((item) => {
res+=item
})
console.log(res)
}
sum1(1, 2, 3, 4, 5) // 15
// Spread Operator(扩展运算符)
function sum5 (x = 1, y = 2, z = 3) {
return x + y + z
}
console.log(sum5(...[4]))// 9
console.log(sum5(...[4, 5]))// 12
console.log(sum5(...[4, 5, 6]))// 15
箭头函数
使用 => 定义函数 箭头左边是参数 右边是函数体
基本用法 只有一个参数和函数体只有
return
一条语句时可简写1
2
3
4
5
6// 只有一个参数时 () 可省略 只有一句return时 {} return也可省略
const es6Fun = a => a
// 等价于
const es5Fun = function(a) { return a }
console.log(es6Fun(1)) // 1
console.log(es5Fun(1)) // 1有多个参数时 用
()
将参数包起来1
2const fun = (a,b) => a + b
console.log(fun(1, 2)) // 3函数体有多行代码时 要将多行代码用
{}
包起来1
2
3
4
5
6const fun = (a, b) => {
a = a*a
b = b*b
return a + b
}
console.log(fun(2, 3)) // 13当函数体只有一行return语句且返回的是字面量对象 ,要用
()
将返回值包起来1
2
3
4
5
6
7
8
9
10
11const fun2 = (a, b) => ({a,b})
console.log(fun2(1, 2)) // {a:1, b:2}
// es5 排序实例
var arr = [5,1,3]
arr.sort(function(a,b){
return b - a
})
console.log(arr) // [5, 3, 1]
// es6 箭头函数 排序实例
arr.sort((a, b) => a - b)
console.log(arr) // [1, 3, 5]箭头函数使用注意事项
- 箭头函数不可以使用
yield
,不能用作Generator
生成器函数 函数体内没有自己的
this
对象,内部this对象是定义时上下文(外层作用域)的this对象, 不是调用时的this对象. 不能使用call apply bind去更改其内部的this指向.箭头函数中的this只取决包裹箭头函数的第一个普通函数的this1
2
3
4
5
6
7
8
9function fn(){
console.log(this)
return () => {
console.log(this) // 定义时作用域
}
}
// fn()() // Window window
fn().call({a:2}) // Window window 无法使用 call 改变箭头函数this对象
// fn.call({a:1})() // {a: 1} {a: 1}箭头函数体内没有
arguments
对象,可以用rest
参数代替1
2
3
4
5
6
7
8let fun3 = (...rest) =>{
console.log(rest)
}
fun3(1,2) // [1, 2]
let fun4 = () => {
console.log(arguments)
}
fun4(1,2) // arguments is not defined箭头函数不可以当做构造函数,不可以使用new命令,否则会报错
1
2const Fun = (a, b) => a + b
new Fun(1,2) // Fun is not a constructor
- 箭头函数不可以使用
模块化
es6
中每一个模块
就是一个文件
,希望外部可以读取模块中的内容,就必须使用export
将其暴露出去(导出), 子其他模块使用import
导入1
2
3
4
5// a.js
export const name = 'tew'
// b.js
import { name } from './a.js'
console.log(name) // tew如果要导出多个变量可以将这些变量包装成对象进行模块化导出
1
2
3
4
5
6
7
8
9// a.js
let name = 'tew'
let age = 18
let fn = (name) => `My name is ${name}`
export { name, age, fn }
// b.js
import { name, age, fn } from './a.js'
console.log(fn('Bob')) // My name is Bob
console.log(age) // 18使用
as
对导出变量或导入变量进行重命名1
2
3
4
5
6
7
8
9
10
11
12// a.js
let name = 'tew'
let age = 18
let fn = (name) => `My name is ${name}`
export { name as myName, age, fn as myFn }
// b.js
import { myName as name, age, myFn as fn } from './a.js'
console.log(name) // tew
console.log(fn('Bob')) // My name is Bob
// 直接导入整个模块
// import * as info from './a.js'
// console.log(info.name) // tew默认导出 一个模块只能有一个
export default
默认导出1
2
3
4
5export default function(){
return '默认导出'
}
import fn from './a.js'
console.log(fn()) // 默认导出混合导出 同时有
export
和export default
1
2
3
4
5
6
7
8
9// a.js
export default function(){
return '默认导出'
}
export let name = 'tew'
// b.js
import fn, {name} from './a.js'
console.log(fn()) // 默认导出
console.log(name) // tew
Proxy
proxy用于修改某些操作的默认行为,在目标对象架设一层拦截,访问该对象时,都必须先通过这层拦截,可以对访问进行过滤和改写
- 基础用法
1
2// var proxy = new Proxy(target, handler)
// new Proxy() 生成一个proxy实例,target表示所要拦截的目标对象,handle对象参数用来定制拦截行为
Generator构造器函数
Generator函数是ES6提供的一种异步编程解决方案,是一个状态机,封装了多个内部状态,返回一个遍历器对象,可以依次遍历Generator函数内部的每一个状态
- Generator函数的定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// 1. Generator函数是一个普通函数,function关键字与函数名之间有一个星号 *
function * foo () {...}
function *foo () {...}
function* foo () {...}
function*foo () {...}
// 由于没有规定 星号 * 的位置所以上述四种写法都可以使用
// 2. 函数内部使用yield表达式,定义不同的内部状态
function* helloGenerator() { // 定义三个状态 hello world ending
yield 'hello'
yield 'world'
return 'ending'
}
// 调用Generator函数后,该函数并不执行,返回的也不是运行结果,而是指向内部状态的指针对象(遍历器对象)
var hg = helloGenerator()
// 调用遍历器对象的next方法,使得指针移向下一个状态,每次调用next内部指针就从上一次状态开始执行,直到遇到下一个yield或return
hg.next() // {value: 'hello', done: false}
hg.next() // {value: 'world', done: false}
hg.next() // {value: 'ending', done: true}
hg.next() // {value: undefined, done: true}
/* 调用Generator函数,返回一个遍历器对象,代表内部指针,每次调用next方法,会返回value和done两个属性的对象,
value表示当前yield表达式的值,done属性表示遍历是否结束, 遇到yield表达式,暂停执行后面的操作,并将紧跟在yield
后面的表达式的值,作为返回对象的value值,遇到return语句,将return后面表达式的值作为返回对象value的值,并将done
属性设置为true,如果没有return语句,则返回对象的value值为undefined,done属性为true */
// for...of 循环可以自动遍历 Generator函数 生成的 Iterator 对象,且不需要调用next方法
for (let v of helloGenerator()) {
console.log(v)
}
// hello world // 一旦next方法返回的对象的done属性为true,循环就会中止,且不包含该对象(即不包含ending)