1、let const
新加声明
let:
- 不能重复声明
- 块级作用域
- 可修改let变量的值
const:
- 不可重复声明
- 块级作用域
- 不可修改const常量的值
2、箭头函数
- 箭头函数改变了this指向
- 如果只有一个参数,() 可以去掉
- 函数体如果只有一句return 语句,花括号可以去掉
let a =function(arg){
return arg+1
}
// 定义一个箭头函数
let a = (arg)=>{ // 这里=>符号就相当于function关键字
return arg+=1
}
// 也可以简写为
let a = arg => arg+=1
3、解构
允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这就是解构。
var [a,b] = [1,2]
// a=1 b=2
规则:
- 左右解构必须一致
- 右边必须是一个合法的数据
- 声明和赋值必须一句话完成,不能把声明和赋值分开
let [a, b] = [1, 2] // 左右都是数组,可以解构赋值
let {a, b} = {a:1, b:2} // 左右都是对象,可以解构赋值
let [obj, arr] = [{a:1}, [1, 2]] // 左右都是对象,可以解构赋值
let [a, b] = {a:1, b:2} // err 左右结构不一样,不可以解构赋值
let {a,b} = {1, 2} // err 右边不是一个合法的数据,不能解构赋值
let [a, b];
[a, b] = [1, 2] // err 声明与赋值分开,不能解构赋值
4、字符串
1、拼接字符串
let name = 'Jone'
`hello ${name},
how are you
`
2、新增三个方法startsWith(), endsWith(), includes()
- startWith表示字符串是否在原字符串的头部,返回布尔值
- endsWith表示字符串是否在原字符串的尾部,返回布尔值
- includes表示是否在原字符串中找到了参数字符串,返回布尔值
这三个方法都支持第二个参数,表示开始搜索的位置。
let s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
5、数组
1、扩展运算符(…),它可以将一个数组拆分为参数序列,也可以收集剩下的所有的参数或者数组元素。
// 将一个数组拆分为参数序列
let arr = [1,2]
function add (a,b) {
return a+b
}
add(...arr)
// 收集剩下的所有的参数
function f(a, ...arr) {
console.log(...arr) // 2 3
}
f(1,2,3)
// 用于数组复制
let arr1 = [1,2]
let arr2 = [...arr1] // 或者let [...arr2] = arr1
let object1 = {
a: 1,
b: 2,
c: 3
};
//最简单的深拷贝:先把对象使用JSON.stringify()转为字符串,再赋值给另外一个变量,然后使用JSON.parse()转回来即可
let object2 =JSON.parse( JSON.stringify(object1));
object2.a=11;
console.log(object1,object2);
// Object { a: 1, b: 2, c: 3 } Object { a: 11, b: 2, c: 3 }
6、promise
promise就是用同步的方式写异步的代码,用来解决地狱回调问题。
promise有三种状态:pending进行中、fulfilled已完成、rejected已失败。
promise状态一旦改变,就不会再变,任何时候都可以得到这个结果。与事件(event)不同,事件的特点是:如果你错过了它,再去监听,是得不到结果的。
优点:
- 将异步操作以同步操作的流程表达出来,避免层层嵌套的回调
缺点:
- promise一旦建立就会立即执行,无法中途取消
- 如果不设置回调函数,promise内部抛出的错误不会反应到外部
- 当处于pending状态,无法得知目前进展(刚开始还是即将完成)
使用方式:
let promise = new Promise((resolve, rejecct) => {
// ... some code
if (/* 异步操作成功*/) {
resolve(value);
} else {
reject(error);
}
})
promise.then(value => {
// 成功的回调
}, error => {
// 失败的回调
})
例子:axios和promise异步调用接口获取数据
import Axios from 'axios';
import Qs from 'qs';
let axios = Axios.create({
baseURL: '', // 基础url前缀
headers: {'Content-Type': "multipart/form-data"}
});
function fetchApi (url) {
return new Promise((resolve, reject) => {
let params = {
// ... some coed
}
// Qs.stringify - 防止post请求参数无法请求到后台
axios.post(url, param)
.then(response => {
resolve(response.data);
}, error => {
reject(error);
})
.catch(err => {
reject(error)
})
});
}
常用方法:
1)promise.prototype.then()
runAsync1()
.then(data => {
console.log(data);
return runAsync2();
})
.then(data => {
console.log(data);
return runAsync3();
})
.then(
data => console.log(data),
err => console.log(err)
);
//上面代码中,异步任务1执行成功后,再执行异步任务2,异步任务2成功后,再执行异步任务3
//runAsync() 返回的是 Promise 对象,通过 then() 函数进行相应/操作。如此情况,称作是“链式操作”
2)Promise.prototype.catch()
getJSON('/post.json')
.then(post => {
// 状态变为 resolved 时调用
// ... some code
})
.catch(error => {
// 状态变为 rejected 时调用
// then方法指定的回调函数,如果运行中抛出错误,也会掉用
console.log('发生错误', error);
})
3)Promise.prototype.finally()
promise
.then(result => {···}) // 状态变为 resolved 时调用
.catch(error => {···}) // 状态变为 rejected 时调用
.finally(() => {···}); // 始终都会执行
4)promise.all()方法
提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
//买作业本
function cutUp(){
console.log('挑作业本');
var p = new Promise(function(resolve, reject){ //做一些异步操作
setTimeout(function(){
console.log('挑好购买作业本');
resolve('新的作业本');
}, 1000);
});
return p;
}
//买笔
function boil(){
console.log('挑笔芯');
var p = new Promise(function(resolve, reject){ //做一些异步操作
setTimeout(function(){
console.log('挑好购买笔芯');
resolve('新的笔芯');
}, 1000);
});
return p;
}
Promise.all([cutUp(),boil()]).then(function(results){
console.log("写作业的工具都买好了");
console.log(results);
});
//挑作业本
//挑笔芯
//挑好购买作业本
//挑好购买笔芯
//写作业的工具都买好了
//[“新的作业本”,“新的笔芯”]
5)promise.race()方法
只要有一个异步操作执行完毕,就立刻执行 then 回调
Promise.race([cutUp(), boil()]).then(function(results){
console.log("哈哈,我先买好啦");
console.log(results);
});
// 挑作业本
//挑笔芯
//挑好购买作业本
//哈哈,我先买好了
//新的作业本
//挑好购买笔芯
7、Generator函数
generator可以理解为生成器,和普通函数没有什么区别。普通函数是只要开始执行,就一直执行到底,而generator函数是中间可以暂停,搭配next函数继续执行。
function * fn(){
alert('a')
yield
alert('b')
}
var f = fn()
f.next() // a
f.next() // b
直接调用Generator函数,是什么都不执行的,调用第一个next()才开始执行,一直执行到第一个yield停止,第二次调用next(),从第一个yield执行到第二个yield停止,依次类推
8、async await
async其实是对generator的封装,只不过async可以自动执行next()。
(1)async返回值
async默认返回一个promise,如果return不是一个promise对象,就会被转为立即resolve的promise,可以在then函数中获取返回值。
async必须等到里面所有的await执行完,async才会开始return,返回的promise状态才会改变,除非遇到return和错误。
async function fn () {
await 100
await 200
return 300
}
fn().then(res => {
console.log9(res) // 300
})
(2)await
await也是默认返回promise对象,如果await后面不是一个promise对象,就会立即resolve的promise。
如果一个awai后面的promise如果为reject,那么整个async都会中断执行,后面的await都不会执行,并且抛出错误,可以在async的catch中捕获错误。
async function f() {
await Promise.reject('error');
await Promise.resolve('hello world'); // 不会执行
}
f().then(res =>{
}).catch(err=>{
console.log(err) // error
})
如果希望一个await失败,后面的继续执行,可以使用try…catch或者在await后面的Promise跟一个catch方法:
// try...catch
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v)) // hello world
// catch
async function f() {
await Promise.reject('出错了')
.catch(e => console.log(e)); // 出错了
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v)) // hello world