简介

es6是什么

es6 全称为 ECMAScript6.0 又称es2015,指2015年发布的版本
其中 ECMA 是一套标准 Script是实现 简单来说就是使用javascript来实现ECMA6.0
es6 又被称为ecma6.0 其实都是一样的

兼容性问题

在目前市面上还是有一些浏览器(IE)不支持es6语法,es5更能做好兼容性问题,所以在有些时候需要将es6转换为es5
通常会使用babel等工具来进行转换

新特性

es6推出的新特性主要是为了解决或优化es5中的各种缺陷

变量

在es5中的 var变量 存在的问题:

  1. 可以重复声明

    1
    2
    3
    4
    var a = 10;
    var a = 5;
    consloe.log(a)
    //此时控制台会将5 打印出来
  2. 无法限制修改,不够严谨。在开发中,会有一些变量的值被固定死,无法被改变,例如圆周率 PI,而var则无法做到

    1
    2
    3
    var pi = 3.1415926
    pi = 1000
    //这里的pi可以被修改
  3. 没有块级作用域,就是变量的作用域

1
2
3
4
5
for(var i =0;i<10;i++){
consloe.log(i)
}
consloe.log(i)
//在循环中定义的变量i 在外部也可以被拿到并使用

const常量

const定义的变量被称为常量,对常量赋值以后就不允许进行修改,其通常使用大写

1
2
const PI = 3.1415926
PI = 100

let局部变量

let定义的变量只能在当前作用域使用,在外部不可以访问

const变量同上,在某个作用域定义的变量只能在某个作用域生效 ,用{}包起来的都算一个作用域

箭头函数

箭头函数主要有两大作用:

  1. 简化写法
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
29
//1.改造普通函数
//es5 中定义函数
function 函数名(){
//执行
}

//es6 中的箭头函数
let 函数名 = ()=>{
//执行
}
// 相比普通函数写法,箭头函数做了一定简化,其过程是
// 1.把function去掉
// 2.在()后面加上 =>

//2.有且只有一个参数时,可以省略()
function add(a){
consloe.log(a)
}

let add = a=>{
consloe.log(a)
}

//3.函数体中有且只有一句retrun语句时,可以省略retrun和{}
function add(a,b){
retrun a+b
}

let add = (a,b)=>a+b
  1. 改变this指向

    在es5中 函数中的this 指示的是函数本身

1
2
3
4
5
6
7
function showName(){
//在函数内定义了一个变量值为张三
personName = '张三'

//使用this指向函数本身,拿到函数内定义的变量,张三就会被打印出来
console.log(this.personName)
}

在es6中,箭头函数没有自己的this,它的this是继承而来,所以当在箭头函数中使用this时,箭头函数中所使用的this就来自于函数作用域链

在浏览器中就会打印出Window 对象

参数收集/展开

当要传递多个参数时,可以使用 …args 的方式

解构赋值

可以在定义变量的时候进行赋值

其中:

  1. 两边结构必须相同
  2. 右边的值必须是一个合法的数据类型
  3. 声明和赋值不能分开
1
2
let [json,arr,num,str] = [{name:'张三'},[1,2,3],15,'abcd']
console.log(json,arr,num,str)

对象简写

1
2
3
4
5
6
7
8
9
10
11
12
let name = 'fish'
let age = 18
let hall = 180

//当对象里面的属性值,与已有变量名同名的话,可以直接赋值
var person = {
name,
age,
hall
}
console.log(person)
//输出 { name: 'fish', age: 18, hall: 180 }

数组

  1. filter过滤器

对一个数组进行循环,当满足条件的时候,将值赋给新变量,如果不符合则去除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let arr = [10,11,12,13,14,15]

// 将数组遍历 赋值给item
let res = arr.filter(function(item){

if(item %2 == 0){
//return trun 表示将值留下 反之剔除
return true
}
return false
})

console.log(res)

1
2
3
//简写
let arr = [10,11,12,13,14,15]
let res = arr.filter(item=>item%2==0?true:false)
  1. forEach 遍历
1
2
3
4
5
let arr = [1,2,3,4,5,]
arr.forEach((item,index)=>{
//快速遍历数组的值跟索引
console.log(item,index)
})
  1. map 将数组里的每一个元素都进行对应处理
1
2
3
4
5
6
7
var arr = [{name:'张三',age:15},{name:'李四',age:16},{name:'王五',age:17}]
var newarr = arr.map(ele()=>{
ele.age = ele.age+1;
ele.check = true;//添加新字段
return ele
})
console.log(newarr);

字符串

  1. startsWith() 和endsWith()
1
2
3
4
5
6
7
8
9
10
var str = 'https://fishband.github.io'

//可以判断该字符串是否以 https开头,若符合,则返回true
console.log(str.startsWith('https'))


var str2 = 'demo.jpg'

//可以判断该字符串是否以 .jpg结尾,若符合,则返回true
console.log(str2.endsWith('.jpg'))
  1. 字符串拼接
1
2
3
4
5
6
7
8
9
10
11
12
let name = 'fish'
let age = 18

//使用 ` (反单引号) 和 ${}(占位符) 来进行字符串拼接,且支持换行操作
let str = `the first variable is ${name},the second is ${age}`

let str1 = `
<div>
${name}
<h1>${age}</h1>
</div>
`

面向对象

  1. 定义类
1
2
3
4
5
6
7
8
9
//定义类
class User{
name = 'fish'
pwd = 123

showName(){
console.log(this.name)
}
}
  1. 静态成员
1
2
3
4
5
6
7
8
//定义类
class User{
name = 'fish'
static rename = 'fishh'
}
let user = new User()
console.log(user.name)
console.log(User.name)
  1. get 和 set
1
2
3
4
5
6
7
8
class User{
get name(){
console.log('读取name')
}
set name(newName){
console.log(`name 被赋值 ${newName}`)
}
}
  1. 继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//定义类
class User{

//定义构造器(构造函数)
constructor(name,pwd){
this.name = name
this.pwd = pwd
}

showName(){
console.log(this.name)
}
}

class VipUser extends User{
constructor(name,pwd,lev){
super(name,pass) //执行父类的构造函数
this.lev = lev //然后加上自己的东西
}

showLev(){
console.log(this.lev)
}
}

模块化

es6之前的三种模块化规范:

  1. CommonJS ==> NodeJS、Browserify
  2. AMD ==> requireJS
  3. CMD ==> seaJS

导出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//1. 单独暴露
//通过exprot 导出
export let name = 'fish'
export let eat = name=>{
console.log(`${name} is eatting`)
}


//2. 同一暴露
export let name = 'fish'
export let eat = name=>{
console.log(`${name} is eatting`)
}
export {name,eat}


//3. 默认暴露
// 花括号中的所有数据都会暴露出去
export default {
name:'fish',
eat = name=>{
console.log(`${name} is eatting`)
}
}

引入:

1
2
3
4
5
6
7
8
9
10
11
12
//1. 通用
import * as m1 from 'fileUrl'

//2. 解构赋值形式
//可以通过as 别名 来避免重名和关键字
import {name as n1,eat} from "fileUrl"

//3. 简便形式,只能针对默认暴露
import m3 from "fileUrl"

//4. 引入npm包
import $ from 'jquery'

Promise

在学习Promise之前我们需要先熟悉两个东西 异步和同步

异步

发起请求后,响应回来需要一段时间,我们没必要等到数据回来才干其他的事,我们可以先执行别的操作,等到数据回来的时候再去执行对应的方法。这样的话用户体验就很好,如果服务器堵塞的时候用户端不会卡住。

但是: 使用异步操作,代码会非常混乱,如果嵌套多层可能会形成回调地狱

同步

一次只能进行一次操作,代码从上至下运行,例如发起请求后会一直等服务端的响应,在此期间只能等待。

而同步对于异步的好处是 :代码非常清晰易懂,易维护

promise完美的融合了同步和异步的优点,它既有异步的高效性又有了同步的代码清晰,可以以同步的形式进行异步操作,是一种合适的解决方案

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
//定义promise
let p = new Promise((resovle,reject)=>{
//异步操作
//参数中的 resovle和reject 就是promise的两种状态,成功和失败

$.ajax({
url:'url',
dataType:'json',
success(arr){
resolve(arr)//如果成功 就使用resolve,并把拿到的数据传给resolve
},
error(err){
reject(err)//如果失败,就使用reject,并把错误传给就使用reject
}
})
})

//当代码执行结束之后,就会回调then,其中有两个参数,第一个函数对应上面的resolve函数,第二个则对应reject函数。当上面代码执行成功,调了resolve方法,并把数据进去了,那么就可以在then中取到
p.then(arr=>{
console.log('成功')
console.log(arr)
},err=>{
consele.log('失败')
console.log(err)
})

其实 promise 本质上更倾向于把异步操作封装成同步操作,当然它也有自己的一个简单的函数all() ,就是当我们想要同时发起多个请求时,我们就可以使用 Promise.all()

Promise.all() 只有当参数列表中的所有请求都成功时,才算成功,成功后一次性将数据全部返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Promise.all([
//all方法的参数为 一个数组
$.ajax({url:'url1'},{dataType:'json'}),
$.ajax({url:'url2'},{dataType:'json'}),
$.ajax({url:'url3'},{dataType:'json'})
])
//它的回调也是一个数组,对应参数中的数组
.then(([data1,data2,data3])=>{
data1.forEach(item=>{
console.log(item)
})
},res=>{
console.log(err)
})

Promise 中还有一个 Promise.race()方法,它会同时请求参数列表中所有请求,哪一个先完成就使用哪一个,除非全部都失败了才会走error。使用场景不多,我们稍微了解一下

1
2
3
4
5
Promise.race([
$.ajax({url:'url1'},{dataType:'json'}),
$.ajax({url:'url2'},{dataType:'json'}),
$.ajax({url:'url3'},{dataType:'json'}),
])

Generator

yield:

  1. Generator函数跟普通函数差别不大,区别是 Generator函数不是一次性全部执行完的,而是通过next()方法,每调用一次,函数就往下执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
//定义Generator函数,在function和函数名之间加一个 * ,注意三者不要黏在一起即可
function * show(){
console.log('a')
yield //当函数运行到yield语句时,就会停止
console.log('b')
yield
console.log('c')
}

let show1 = show()//使用前需要接收一下Generator函数
show1.next()//每执行一次next方法,函数就会往下执行
show1.next()
show1.next()
  1. 传递参数
1
2
3
4
5
6
7
8
9
10
11
12
// 向外传递参数
function * show(){

let name = 'fish'

// 在函数内部获得的参数,可以通过yield 传递出去
yield name
}

let show1 = show()
console.log(show1.next())
// 打印出 {value:'fish',done: false}

向内传递参数

async/await

async与Generator都是一种函数的特别形式,但是它彻底的糅合了同步和异步

当运行到await 时,程序会“暂停”,其实内部会把函数根据await 切成若干个小函数一个一个执行,当异步完成后才往下执行,将异步操作封装成了同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var url = 'url'
var dataType = 'json'

//声明了函数当中有异步操作
async functiong show(){

try{

//声明异步操作
let data = await $.ajax({
url,
dataType
});

}catch(err){//使用assync时,要用catch来捕获错误
console.log(err)
}
}