ES6(ECMAScript 6)是 JavaScript 的下一代标准。当前版本的 ES6 是在2015年6月发布的,所以又称 ECMAScript 2015。也就是说,ES6 就是 ES2015。ES6 是 ECMAScript 标准十余年来变动最大的一个版本,新增了许多新的语法特性。虽然目前并不是所有浏览器都能兼容 ES6 全部特性,但越来越多的程序员在实际项目当中已经开始使用 ES6,同时这也是很多大厂前端岗面试的重点之一。
这篇博客详细介绍了 ES6 的部分常用语法,在后续的Vue学习笔记系列中会用到。
let 块级作用域
作用域即变量在什么范围内是可用的。ES5中的var
是没有块级作用域的,包括if块和for块,这会引起一些问题:
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
{
var btns = document.getElementsByTagName('button')
for(var i=0; i<btns.length; i++){
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击了')
})
}
}
</script>
这样的结果是,点击每个按钮,打印出的都是“第5个按钮被点击了”。
在ES5中,可以用闭包解决上述问题,因为函数是有作用域的,给函数传入的变量作为参数,在函数内不会受到变量在函数外改变的影响。所以在很多时候,我们都必须借助于函数作用域来解决应用外面变量的问题。
var btns = document.getElementsByTagName('button')
for(var i=0; i<btns.length; i++){
(function (num) {
btns[num].addEventListener('click', function () {
console.log('第' + num + '个按钮被点击了')
})
})(i)
}
而ES6中的let
是有块级作用域的。只要把for循环中的var i=0
改为let i=0
即可轻松解决上述问题。
var btns = document.getElementsByTagName('button')
for(let i=0; i<btns.length; i++){
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击了')
})
}
const 常量
const
修饰的标识符为常量:
- 一旦赋值,不能修改
- 声明时,必须赋值
- 常量的含义是指向的对象(地址)不能修改,但是可以改变对象内部的属性
- const是有块级作用域的
建议在ES6开发中,优先使用const,只有需要改变某一个标识符的时候才使用let
对象字面量的增强写法
属性的增强写法
const name = 'Perry'
const age = 22
//ES5
const obj = {
name: name,
age: age
}
//ES6
const obj = {
name,
age
}
函数的增强写法
//ES5
const obj = {
run: function () {
console.log('running')
}
}
//ES6
const obj = {
run(){
console.log('running')
}
}
箭头函数
箭头函数也是一种定义函数的方式,箭头左边为函数参数,右边为函数体。当把一个函数作为参数传到另一个函数中时经常使用箭头函数。
//常规写法
const add = (a,b) => {
return a + b
}
//函数只有一个参数时可以省略小括号
const power = num => {
return num * num
}
//函数体中只有一行代码时可以省略大括号和return
const mul = (a,b) => a * b
注:function定义的函数中的 this引用的是 window,箭头函数中的 this引用的是向外一层作用域的 this。
Promise 异步
Promise:异步编程的一种解决方案。当开发中有异步操作时,可以用Promise对异步操作进行封装。
异步的应用场景:网络请求。我们封装一个网络请求的函数,因为不能立即拿到结果返回,用户界面可能会阻塞,所以往往需要传入另一个函数,在数据请求成功后,执行这个回调函数,使用数据。
回调地狱:回调函数里又有回调函数,一层又一层。Promise可以以一种非常优雅的方式来解决这个问题。
Promise的基本使用
Promise是一个类,new创建Promise对象时需要传入一个函数作为参数,这个函数的参数也是两个函数:
- resolve:异步操作成功的时候调用,可以通过参数把数据传入到then的处理函数中。
- reject:异步操作失败的时候调用,可以通过参数把数据传入到catch的处理函数中。可选参数。
new Promise((resolve, reject) => {
//异步操作代码,如网络请求
setTimeout(() => {
resolve('Hello')
// reject('Error')
}, 1000)
}).then(data => {
//异步操作成功的处理代码
console.log(data);
}).catch(err => {
//异步操作失败的处理代码
console.log(err);
})
另一种写法:不用catch,给then传入两个参数,分别是是异步操作成功和失败的处理函数。
new Promise((resolve, reject) => {
...
}).then(data => {
console.log(data);
}, err => {
console.log(err);
})
Promise的三种状态:
- pending:等待状态。比如正在进行网络请求时,或者定时器没有到时间。
- fulfill:满足状态。当主动回调了resolve时,就处于该状态,并且会回调then。
- reject:拒绝状态。当主动回调了reject时,就处于该状态,并且会回调catch。
Promise的链式调用
异步操作(网络请求)的代码在Promise对象里,所有处理的代码都在上一个Promise对应的then里。
new Promise(resolve => {
setTimeout(() => {
console.log('网络请求...得到结果:aaa');
resolve('aaa')
}, 1000)
}).then(res => {
console.log('第一层处理代码...得到结果:aaa111');
return new Promise(resolve => {
resolve(res + '111')
})
}).then(res => {
console.log('第二层处理代码...得到结果:aaa111222');
return Promise.resolve(res + '222')
}).then(res => {
console.log('第三层处理代码...');
console.log(res);
}).catch(err => {
console.log(err);
})
注:如果某一步主动回调了 reject,则后面所有的 then处理代码都不再执行,直接回调最后的 catch。
链式调用中 return new Promise() 的简写:
//原始写法
return new Promise(resolve => {
resolve(res + '222')
})
return new Promise((resolve, reject) => {
reject('error message')
})
//一次简写
return Promise.resolve(res + '222')
return Promise.reject('error message')
//二次简写
return res + '222'
throw 'error message'
Promise的all方法
有时候一个需求可能依赖两个网络请求,只有两个请求都完成,才能进行下一步。Promise可以使用all方法,实现同时处理多个异步操作,当所有操作都完成的时候,再在统一的地方拿到所有操作的结果。
Promise.all([
new Promise((resolve, reject) => {
console.log('网络请求一...得到结果:res111');
resolve('res111')
}),
new Promise((resolve, reject) => {
console.log('网络请求二...得到结果:res222');
resolve('res222')
})
]).then(results => {
console.log(results[0]); //res111
console.log(results[1]); //res222
})
数组遍历
遍历数组下标:
- for (let i=0; i<this.arr.length; i++) { }
- for (let i in this.arr) { }
遍历数组元素:
- arr.forEach (function (val) { })
- ES6语法:for (let val of this.arr) { }
其他语法
- 面向对象:class声明类,extends继承类,super访问父类。
- 解构:从对象或数组中提取值,对变量进行赋值。
- 函数默认参数:声明函数时default设置默认参数,用于调用函数时没有传参的情况。
- 模板字符串:``反引号,${}模板占位符。