我是从使用react开始在实际项目中使用es6语法的,转眼间已经过去了两年,中间从react到react-native再到node,es6有些语法确实方便很多,但是对其仅限于能用,了解的并不深入,所以想写篇笔记,记录下对es6语法的新认识,希望自己能够持续更新,不断进步。
为什么叫ES6
ES2015特指在2015年发布的新一代JS语言标准,ES6泛指下一代JS语言标准,包含ES2015、ES2016、ES2017、ES2018等。现阶段在绝大部分场景下,ES2015默认等同ES6。ES5泛指上一代语言标准。ES2015可以理解为ES5和ES6的时间分界线。
babel
之前在使用react的时候,webpack总是需要使用babel,babel的作用是编译es6,把es6编译成es5。就像java文件需要编译成class才能在电脑上运行,stylus、sass、less等css预处理需要编译成css才能在浏览器中运行,es6也一样,他不能直接在浏览器中执行,有些浏览器并不支持es6语法,所以需要使用babel将es6语法的代码转译成es5才能在浏览器中执行。
let与var
在ES6之前,声明变量只能用var,var方式声明变量其实是很不合理的,准确的说,是因为ES5里面没有块级作用域,let 声明的变量拥有自己的块级作用域,且修复了var声明变量带来的变量提升问题。
字符串includes方法
ES6在String原型上新增了includes()方法,用于取代传统的只能用indexOf查找包含字符的方法,indexOf返回-1表示没查到不如includes方法返回false更明确,语义更清晰
箭头函数的this指向
在使用react时,最开始声明对象方法是直接声明函数
class App extends Component{
testHandle(){
this.setState({})
}
render(){
return <Fragment>
<div
onClick={this.testHandle}
>这里是测试</div>
</Fragment>
}
}
上面的代码中testHandle中的this在调用时是undefined,解决办法有三种
第一种
class App extends Component{
testHandle(){
this.setState({})
}
render(){
return <Fragment>
<div
onClick={this.testHandle.bind(this)}
>这里是测试</div>
</Fragment>
}
}
可以通过bind方法改变函数中this指向,只不过每次使用都得bind,非常繁琐
第二种
class App extends Component{
constructor(props){
super(props)
this.testHandle = this.testHandle.bind(this);
}
testHandle(){
this.setState({})
}
render(){
return <Fragment>
<div
onClick={this.testHandle}
>这里是测试</div>
</Fragment>
}
}
第二种是在构造函数constructor中bind一次,之后使用的时候就不用再bind了,这种方式比第二种方式简单了不少
第三种
class App extends Component{
testHandle = ()=>{
this.setState({})
}
render(){
return <Fragment>
<div
onClick={this.testHandle}
>这里是测试</div>
</Fragment>
}
}
第三种是使用箭头函数去声明,我之前的理解是这种声明方式是先声明类的一个属性testHandle在把函数赋值给该属性,因为该属性是类的所以函数中的this就永远指向this,但是今天看到关于箭头函数的一个定义
箭头函数内的this指向的是函数定义时所在的对象,而不是函数执行时所在的对象
也就是说在定义时,他的this指向谁,之后调用的时候就指向谁,这种方式也是最方便的方式,原因是箭头函数没有this,他的this是在他声明的时候确认的且一旦确认就不可改变
ES6的箭头函数优化了这一点,它的内部没有自己的this,这也就导致了this总是指向上一层的this,如果上一层还是箭头函数,则继续向上指,直到指向到有自己this的函数为止,并作为自己的this;
箭头函数不能用作构造函数,因为它没有自己的this,无法实例化;
也是因为箭头函数没有自己的this,所以箭头函数 内也不存在arguments对象。
ES6数组扁平化
ES6提供了Array.flat()
方法实现数组扁平化,他接受一个参数,可以是数字或者是Infinity,代表扁平化到第几个维度,适用于多维数组,默认值为1,该方法会移除数组中的空项
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5] 空项被移除
对象合并Object.assign()
之前在使用jquery封装插件的时候经常使用$.extend()
方法合并对象,ES6中提供了合并对象的方法Object.assign()
,他的使用方法和$.extend()
的使用方法是一样的,都是传入多个对象,然后后面的对象向前面的对象合并,有冲突的属性会覆盖
const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target) // {a:1, b:2, c:3}
遍历数组与对象
1、forEach
forEach
方法他接收三个参数分别为value、index、arr,分别代表:值,索引,遍历的数组
(1)该方法只能遍历数组,不能遍历对象
(2)该方法没有返回值
(3) 该方法不能通过break和continue的方式停止循环及跳过当次循环
let arr = [1,2,3,4,5]
let result = arr.forEach((value,index,arr)=>{
console.log(value) //值
console.log(index) //索引
console.log(arr) //原数据[1,2,3,4,5]
})
console.log(result) //undefined
2、map
map()
方法他也是接受三个参数分别为value、key、obj,分别代表:值,键,遍历的对象
(1)该方法只能遍历数组,不能遍历对象
(2)该方法有返回值
(3) 该方法不能通过break和continue的方式停止循环及跳过当次循环
let arr = [1,2,3,4,5]
let result = arr.map((value,index,obj)=>{
console.log(value) //值
console.log(index) //索引
console.log(obj) //原数据[1,2,3,4,5]
return value
})
console.log(result) //[1,2,3,4,5]
3、for in
(1)该方法既可以遍历数组,也可以遍历对象
(2)该方法可以通过break和continue的方式停止循环及跳过当次循环
const arr = ["a","b",1,true]
for (const index in arr) {
const value = arr[index]
console.log(value)
}
let obj = {"a":1,"b":2,"c":3,"d":4}
for (const key in obj) {
const item = obj[key]
if(key == "b"){
break
}
console.log(key)
}
4、Object.keys(),Object.values()
这两个方法对数组及对象都有作用,Object.keys()
返回数组的索引或者对象的属性,Object.values()
返回数组的值或者对象的值
const arr = ["a","b",1,true]
let obj = {"a":1,"b":2,"c":3,"d":4}
console.log(Object.keys(arr)) //["0","1","2","3"]
console.log(Object.values(arr)) //["a","b",1,true]
console.log(Object.keys(obj)) //["a","b","c","d"]
console.log(Object.values(obj)) //["a","b","c","d"]
Object.keys(obj).forEach(key=>{
let item = obj[key]
})
Promise的执行顺序
promise是异步回调地狱的解决方案,大体的实现形式如下
const request = new Promise((resolve,reject)=>{
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
}).then((res)=>{
resolve(res)
}).catch((error)=>{
reject(error)
})
})
request().then((res)=>{
console.log(res)
}).catch((error)=>{
console.log(res)
})
resolve执行成功的回调,reject执行失败的回调,在的执行顺序上:Promise的回调函数是同步执行的,而Promise的链式调用then和catch方法是异步执行的
new Promise(resolve=>{
console.log(1)
resolve(3)
}).then(num=>{
console.log(num)
})
console.log(2)
上面的代码最后输出的结果是123,首先Promise回调函数是同步执行的,所以console.log(1)
会首先执行,然后then是异步执行,所以先执行console.log(2)
,最后执行console.log(num)
,num是resolve(3)穿的参数,所以是3
参考资料:
https://mp.weixin.qq.com/s/aiG3eackQShKhwleVlhwww
网友评论