Skip to main content

ES6

ES6版本变动内容最多,加入了许多新的语法特性,编程实现跟简单、高效;是前端发展的趋势,vue、react等前端框架基本上都是使用的ES6版本语法,目前已基本不用考虑ES6兼容性,应为后面我们可以通过babel进行转换

1、新增变量声明关键字#

1.1、let#

(1)、使用let关键字声明变量

let age=18let name="is-zhou"
特性:
① 具有块级作用域
② 不存在变量提升
③ 不能重复声明
④ 不影响作用域链效果
⑤ 且有暂时性死区特性(在赋值之前不可访问,如果访问了会抛出ReferenceError错误)

1.2、const#

(1)、使用const关键字声明常量

const AGE=18
特性:
① 具有块级作用域
② 必须赋初始值不然报错
③ 赋值后,不能更改赋值(值指的是指向的内存地址不能改变,如果是对象则对象指向的内存地址不能改变对象/数组的属性可以改变)
④ 不存在变量提升

程序中不改变的值/声明函数尽量使用const关键字声明,javascript引擎不需实时监控效率略高

1.3、is-zhou#

(1)、使用is-zhou关键字声明原始数据类型,表示独一无二的值

let s=Symbol();//此时s拥有唯一值(我们看不到的唯一值)
let s2=Symbol('is-zhou')let s3=Symbol('is-zhou')//s2和s3的值是不相等的唯一值

let s4=Symbol.for('is-zhou')let s5=Symbol.for('is-zhou')//s4和s5的值是相等的唯一值
特性:
① 不能与其他数据进行运算
② 定义的对象属性不能使用for...in...循环遍历
③ 可通过reflect.ownkeys获取对象的所有键名

2、解构赋值#

通过一定的模式和一一对应的关系从 数组/对象 提取值,对变量进行赋值

2.1、数组解构#

(1)、按需解构数组下标对应赋值给左边伪数组中的变量,而且伪数组中的每个变量名都可以直接通过变量名访问

let userList=['张三','李四','王五']let [a,b,c]=userList //按数组下标对应赋值给左边console.log(a)console.log(b)console.log(c)-------------------------------------=>张三=>李四=>王五

(2)、定义的为数组不足需结构数组时多余的不赋值

let userList=['张三','李四','王五']let [a,b]=userListconsole.log(a)console.log(b)-------------------------------------=>张三=>李四

(3)、超出需解构数组数量时赋undefind

let userList=['张三','李四','王五']let [a,b,c,d,e]=userListconsole.log(a)console.log(b)console.log(c)console.log(d)console.log(e)-------------------------------------=>张三=>李四=>王五=>undefined=>undefined

2.2、对象解构#

允许我们使用变量的名字匹配对象的属性,匹配成功则将对象的属性值赋值给变量

(1)、直接使用对象的属性名作为变量名

let person={name:"张三",age:30,sex:"男"}let {name,age,sex}=personconsole.log(name)console.log(age)console.log(sex)-------------------------------------=>张三=>30=>

(2)、指定其他变量名解构

let person={name:"张三",age:30,sex:"男"}let {name:myname,age:myage,sex:mysex}=personconsole.log(myname)console.log(myage)console.log(mysex)-------------------------------------=>张三=>30=>
注意:

解构数组时定义变量使用数组括号[],解构对象时定义变量使用对象括号{}

3、模板字符串#

3.1、反引号 ``定义模板字符串#

(1)、通过反引号包裹字符串的方式声明字符串

特性:
① 模板字符串内容中可以出现换行符
② 可以变量拼接
let name="is-zhou"let text=`你说我是谁?我是${name}`console.log(text)-------------------------------------=>你说我是谁?我是is-zhou

4、对象简化写法#

ES6中允许在大括号里直接写入变量和函数,作为对象的属性和方法

/************ES5写法**************/ //const user={//    name:name,//    age:age,//    sayHi:function(){//        console.log('你好')//    }//}/************ES6简化写法**************/ const user={    name,    age,    sayHi(){        console.log('你好')    }}

5、箭头函数#

5.1、简化函数定义语法#

/************ES5写法**************/ var fn=function(){
}/************ES6简化写法(箭头函数)**************/ const fn=()=>{
}

5.2、特性#

(1)、箭头函数的this是静态的,始终指向的是箭头函数声明时所在的作用域this

(2)、不能作为构造函数实例化对象

(3)、不能使用arguments变量

(4)、不能使用call方法修改this的指向

(5)、如果形参有且只有一个可以省略小括号

const fn=n=>{
}

(6)、如果函数体只有一句代码,且代码的执行结果就是返回值时可以省略大括号和return关键字

const fn=n=>n+1console.log(fn(1))------------------=>2

6、参数#

6.1、函数形参默认值#

ES6允许给函数形式参数赋初始值,具有默认值的参数要靠最后

function add(a,b,c=15){    return a+b+c}
console.log(add(1,2))-------------------------=> 18

6.2、函数剩余参数...args#

(1)、剩余参数...args一定要放在最后

function fn(a,b,...args){    console.log(a)     console.log(b)     console.log(args) }fn(1,2,3,4,5,6);--------------------------------=>1=>2=>[3,4,5,6]

7、扩展运算符...#

7.1、拆分数组序列#

//拆分数组序列let arg1=[1,2,3]let arg2=[4,5,6]console.log(arg1)    -> [1,2,3]console.log(arg2)    -> [4,5,6]
console.log(...arg1) -> 1,2,3console.log(...arg2) -> 4,5,6
let arg3=[...arg1,agr2]console.log(arg3)    ->[1,2,3,4,5,6]

7.2、将为数组转换成真数组#

let mydiv=document.getElementByTayName('div')
let arg=[...mudiv]

8、迭代器#

8.1、for... of...#

for...in...获取的是键名,for...of...获取的是键值

9、Promise#

异步编程解决方案,通过Promise可以解决回调地狱的问题

9.1、将异步任务套在Promise构造函数中#

let myPromise=new Promise((resolve,reject)=>{        此处写异步任务代码块        在异步任务代码的回调函数中如果成功 则调用 resolve("返回值")     如果失败则调用 reject(err)    后面通过Promise实例的 then()方法和 catch()方法分别处理以上调用的成功和失败
})myPromise.then(result=>{    上面Promise对象构造函数中调用了 resolve("返回值") 方法时此处会获得返回值 }).catch(err=>{    上面Promise对象构造函数中调用了 reject(err) 方法时此处会获得err值 })

9.2、将普通函数变成异步函数async#

在普通函数前加 async 关键字,将普通函数变成异步函数
async 关键字的异步函数默认返回 Promise 对象,但是要在函数中使用 return 来代替 Promise 对象的 resolve() 方法使用 throw 来代替 Promise 对象的 reject() 方法
最后调用该函数后可以直接调用 then()方法
async 函数中的 await 关键字只能出现在异步函数中 await 后面只能写 Promise 对象await 关键字只能锁住异步函数向下执行返回 Promise 结果 

9.3 Promise API#

(1)Promise.all() 它的reject回调执行是,只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。

const promise1 = Promise.resolve(3);const promise2 = 42;const promise3 = new Promise((resolve, reject) => {  setTimeout(resolve, 100, 'foo');});
Promise.all([promise1, promise2, promise3]).then((values) => {  console.log(values);});// expected output: Array [3, 42, "foo"]

(2)Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise

const pErr = new Promise((resolve, reject) => {  reject("总是失败");});
const pSlow = new Promise((resolve, reject) => {  setTimeout(resolve, 500, "最终完成");});
const pFast = new Promise((resolve, reject) => {  setTimeout(resolve, 100, "很快完成");});
Promise.any([pErr, pSlow, pFast]).then((value) => {  console.log(value);  // pFast fulfils first})// 期望输出: "很快完成"

(3)、Promise.race() 函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。

10、集合Set#

10.1、声明集合Set#

不存储重复的值,如有重复自动去除

let s=new Set()
let s1=new Set(['a','b','c','d'])

10.2、Set的api#

let s=new Set(['a','a','a'])s                        => 自动去重返回 {"a"}
let s1=new Set(['a','b','c','d'])//元素个数s1.size//添加元素s1.add('e')              =>  直接操作原集合返回 {"a", "b", "c", "d", "e"}  //删除元素s1.delete('a')           =>  直接操作原集合返回 true/false //判断是否存在某个元素s1.has('b')              =>  直接操作原集合返回 true/false //清空集合s1.clear()               =>  直接操作原集合返回 {}

10.3、#

数组去重

let arr=[1,2,3,4,5,5,4,3,2,1]let result=[...new Set(arr)]

11、键值对集合Map#

11.1、声明使用#

let myMap = new Map();
let keyObj = {};let keyFunc = function() {};let keyString = 'a string';
// 添加键myMap.set(keyString, "和键'a string'关联的值");myMap.set(keyObj, "和键keyObj关联的值");myMap.set(keyFunc, "和键keyFunc关联的值");
myMap.size; // 3
// 读取值myMap.get(keyString);    // "和键'a string'关联的值"myMap.get(keyObj);       // "和键keyObj关联的值"myMap.get(keyFunc);      // "和键keyFunc关联的值"
myMap.get('a string');   // "和键'a string'关联的值"                         // 因为keyString === 'a string'myMap.get({});           // undefined, 因为keyObj !== {}myMap.get(function() {}); // undefined, 因为keyFunc !== function () {}

12、class创建对象#

通过class关键字定义类相当于ES5的语法糖写法

(1)、通过class声明类

(2)、constructor定义构造函数初始化

(3)、extends继承父类

(4)、super调用父级构造函数

(5)、static定义静态方法和属性

(6)、父类方法可以重写

12.1、声明创建对象#

/****************ES5定义类******************//*function Phone(brand,price){    this.brand=brand    this.price=price}Phone.prototype.call=function(){    console.log("打电话")}let myPhone=new Phone('华为',666666);*/
/****************ES6定义类******************/class Phone{    //构造方法(固定的名字不能修改该)当通过new实例化对象时会自动执行    constructor(brand,price){        this.brand=brand        this.price=price    }    //方法    //方法必须使用该语法,不能使用ES5的语法    call(){        console.log("打电话");    }}let myPhone=new Phone('华为',666666);

12.2、静态成员static#

注意: 在类中通过`static`关键字声明的对象或属性,即为静态成员,是属于类的不属于实例化的对象,因此该类的实例化对象不能访问该类的静态成员;
实例访问静态属性输出undefined -访问静态方法输出 TypeError
class Phone{    //构造方法(固定的名字不能修改该)当通过new实例化对象时会自动执行    static name="huawei"    constructor(brand,price){        this.brand=brand        this.price=price    }    //方法    //方法必须使用该语法,不能使用ES5的语法    static call(){        console.log("打电话");    }}let myPhone=new Phone('华为',666666);myPhone.name                   =>undefinedmyPhone.call()                 => TypeError: myPhone.call is not a function at <anonymous>:15:9

12.3、对象继承#

子类继承父类后,子类将拥有父类的属性和方法,同时子类可以对父类的方法进行重写

class Phone{    constructor(brand,price){        this.brand=brand        this.price=price    }    call(){        console.log('打电话')    }    playGame(){         console.log('玩单机游戏')    }} 
class SmartPhone extends Phone{    constructor(brand,price,color){        super(brand,price)//调用父类够着函数        this.color=color    }    photo(){         console.log('拍照')    }    //重写父类的playGame方法    playGame(){         console.log('玩网络游戏')    }}
let mySmartPhone=new SmartPhone('华为',666666,"red")mySmartPhone.photo()//调用自己的打电话方法mySmartPhone.call()//调用父类的打电话方法mySmartPhone.playGame()//调用子类重写父类的方法

12.4、get和set方法#

class Phone{    get price(){        return "1000"    }
    set price(newPrice){            }}let s=new Phone();s.price //会触发get price 方法console.log(s.price)    => 1000s.price='free' //会触发set price 方法

12.5、对象方法扩展#

/*******判断两个值完全相等***************/object.is(18,18)     =》返回 truefalse 相当于===
/*******对象合并***************/const obj1={    n1:1,    n2:2}const obj2={    n2:3,    n3:4,    n4:5}object.assign(obj1,obj2)//将obj1和obj2进行合并且有相同的时后面的覆盖前面的

13、模块化modules#

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来,模块化可以有防止命名冲突,代码复用,高维护性等特点

13.1、ES6之前的模块化规范#

commonJS 模块化规范 => NodeJS、Browserify

AMD 模块化规范 => requireJS

CMD 模块化规范 => seaJS

13.2、ES6模块化规范(ES6 modules)#

模块化核心就是导入import和导出export

(1)、直接导出

/*************a.js**************/ export let name="张三"
/*************b.js**************/ import {name} from './a.js' 

(2)、集中导出

/*************a.js**************/ let name="张三"let age=30
export {name,age}
/*************b.js**************/ import {name,age} from './a.js' 

(3)、默认导出

/*************a.js**************/ export default function(){    console.log('默认导出')}
/*************b.js**************/ import myfn from './a.js'  //如果是默认导出,导入时可以自定义名称且不用大括号

(4)、全部默认导入

/*************a.js**************/ let name="张三"let age=30
export {name,age}
import * as a from './a.js' //这样导入可以通过 a即导出的名称进行取值
a.namea.age