ES6入门
常量
ES5中常量的写法
Object.defineProperty(window, 'myPI', {
value: 3.141592653,
writable: false
})
ES6中常量的写法
const PI = 3.141592653
console.log(PI)
PI = 1 // error
作用域
块级作用域的存在
箭头函数
() => {
//***
}
- 小括号内的参数如果只有一个,则可以省略小括号
- 花括号内只存在返回值,则可以省略花括号和return
// ES5写法
arr.map(function(val) {
return val + 1
})
// ES6写法1
arr.map((val) => {
return val + 1
})
// ES6写法2
arr.map(val => val + 1)
函数参数相关知识
ES3/5中默认参数的写法
function f(x, y, z) {
x = x || 1
y = y || 7
z = z || 42
return x + y + z
}
ES6中默认参数的写法
function f(x, y = 7, z = 42) {
return x + y + z
}
ES6中检查参数不为空
function checkParam() {
throw new Error('Param cannot be undefined')
}
function f(x = checkParam(), y = 7, z = 42) {
return x + y + z
}
try {
f()
} catch(e) {
console.log(e)
}
ES3/5 可变参数
function f() {
var a = Array.prototype.slice.call(arguments)
var sum = 0
a.forEach(function(val) {
sum += val
})
return sum
}
console.log(f(1, 2, 3, 4))
ES6 可变参数
function f(...a) {
let sum = 0
a.forEach(val => {
sum += val
})
return sum
}
console.log(f(1, 2, 3, 4))
合并数组
// ES3/5
var arr1 = [1, 2, 3]
var arr2 = [4, 5].concat(arr1)
// ES6
let arr1 = [1, 2, 3]
let arr2 = [4, 5, ...arr1]
ES3/5 数据保护
// ES3
var Person = function() {
var data = {
name: 'es3',
sex: 'male',
age:15
}
this.get = function(key) {
return data[key]
}
this.set = function(key, value) {
if (key !== 'sex') {
data[key] = value
}
}
}
var person = new Person()
// ES5
var Person = {
name: 'es5',
age: 15
}
Object.defineProperty(Person, 'sex', {
value: 'male',
writable: false
})
ES6 数据保护
let Person = {
name: 'es6',
age: 15,
sex: 'male'
}
let person = new Proxy(Person, {
get(target, key) {
return target[key]
},
set(target, key, value) {
if(key !== 'sex') {
target[key] = value
}
}
})
Promise 入门
Promise是什么
- 主要用于异步计算
- 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
- 可以在对象之间传递和操作Promise,帮助我们处理队列
回调的四个问题
- 嵌套层次很深,难以维护
- 无法正常使用return和throw
- 无法正常检索堆栈信息(函数先入栈先出栈,每一次回调都是在系统层面上的一个新的堆栈)
- 多个回调之间难以建立联系(一个回调一旦启用,我们就无法对其进行操作)
Promise 简介
new Promise(
/* 执行器 executor */
function(resolve, reject) {
// 一段耗时很长的异步操作
resolve() // 数据处理完成
reject() // 数据处理出错
}
).then(function A() {
// 成功,下一步
}, function B() {
// 失败,做相应处理
})
- Promise 是一个代理对象,它和原先要进行的操作并无关系
- Promise 通过引入一个回调,避免更多的回调
Promise 的状态
- pending [待定]初始状态
- fulfilled [实现]操作成功
- rejected [被否决]操作失败
Promise状态发生改变,就会触发
.then()里的响应函数处理后续步骤
Promise 状态一经改变,不会再变
.then()
- 状态响应函数可以返回新的Promise,或其他值,或者不返回值
- 如果返回新的Promise,那么下一级
.then()会在新Promise状态改变之后执行 - 如果返回其他任何值或不返回值,则会立刻执行下一级
.then()
小测验
假设doSomething与doSomethingElse及finalHandler函数都返回一个Promise实例,那么下面四中Promise的区别是什么
// #1
doSomeThing().then(function() {
return doSomethingElse()
}).then(finalHandler)
/**
* doSomething ->
* doSomethingElse(undefined) ->
* finalHandler(resultOfDoSomethingElse)
**/
// #2
doSomething().then(function() {
doSomethingElse()
}).then(finalHandler)
/**
* doSomething ->
* doSomethingElse(undefined) + finalHandler(undefined) 几乎同时执行
**/
// #3
doSomething().then(doSomethingElse()).then(finalHandler)
/**
* doSomething + doSomethingElse(undefined) 几乎同时执行 ->
* finalHandler(resultOfDoSomething)
**/
// #4
doSomething().then(doSomethingElse).then(finalHandler)
/**
* doSomething ->
* doSomethingElse(resultOfDoSomething) ->
* finalHandler(resultOfDoSomethingElse)
**/
.catch()
建议在所有队列最后都加上.catch(),以避免漏掉错误处理造成意想不到的问题
Promise.all()
- 批量执行:用于将多个Promise实例,包装成一个新的Promise实例
Promise.all([p1,p2,p3,...])- 数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
- 当所有子Promise都完成,该Promise完成,返回值是全部值的数组
- 有任何一个失败,该Promise失败,返回值是第一个失败的子Promise的结果
console.log('here we go')
Promise.all([1, 2, 3])
.then( all => {
console.log('1:', all)
return Promise.all([ function () {
console.log('ooxx')
}, 'xxoo', false])
})
.then( all => {
console.log('2:', all)
let p1 = new Promise( resolve => {
setTimeout(() => {
resolve('I\'m P1')
}, 1500)
})
let p2 = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve('I\'m P2')
}, 1000)
})
let p3 = new Promise( (resolve, reject) => {
setTimeout(() => {
reject('I\'m P3')
}, 3000)
})
return Promise.all([p1, p2, p3])
})
.then( all => {
console.log('all', all)
})
.catch( err => {
console.log('Catch:', err)
})
// here we go
// 1: [ 1, 2, 3 ]
// 2: [ [Function], 'xxoo', false ]
// Catch: I'm P3
Promise.all()最常见就是和.map*()连用
实现队列
希望动作按照一定顺序、逐个进行
let promise = doSomething()
promise = promise.then(doSomethingElse)
promise = promise.then(doSomethingElsel2)
promise = promise.then(doSomethingElsel3)
第一种方法:使用.forEach()
function queue(things) {
let promise = Promise.resolve()
things.forEach(things => {
promise = promise.then(() => {
return new Promise(resolve => {
doThing(thing, () => {
resolve()
})
})
})
})
return promise
}
queue(['lots', 'of', 'things', ...])
第二种方法:使用.reduce()
function queue(things) {
return things.reduce((promise, thing) => {
return promise.then(() => {
return new Promise(resolve => {
dothing(thing, () => {
resolve()
})
})
})
}, Promise.resolve())
}
queue(['lots', 'of', 'things', ...])
Promise.resolve()
- 参数为空,返回一个状态为fulfilled的Promise实例
- 参数是一个跟Promise无关的值,同上,不过fulfilled响应函数会得到这个参数
- 参数为Promise实例,则返回该实例,不作任何修改
- 参数为thenable,立刻执行他的.then()
thenable 即一个对象内存在一个
then()方法
Promise.resolve()
.then( () => {
console.log('Step 1', value)
return Promise.resolve('Hello', value)
})
.then( value => {
console.log(value, 'World')
return Promise.resolve(new Promise( resolve => {
setTimeout(() => {
resolve('Good')
}, 2000)
}))
})
.then( value => {
console.log(value, ' evening')
return Promise.resolve({
then() {
console.log(', everyone')
}
})
})
// Step 1 undefined
// Hello World
// Good evening
// , everyone
Promise.reject()
返回一个状态为rejected的Promise实例
- Promise.reject()不认thenable
Promise.race()
类似Promise.all(),区别在于它有任意一个完成就算完成
let p1 = new Promise(resolve => {
setTimeout(() => {
resolve('This is p1')
}, 5000)
})
let p2 = new Promise(resolve => {
setTimeout(() => {
resolve('This is p2')
}, 2000)
})
Promise.race([p1, p2])
.then((value) => {
console.log(value)
})
// This is p2 (after 2000 ms)
常见用法
把异步操作和定时器放在一起,如果定时器先触发,就认为超时,告知用户