Es6

let

let声明的是块级作用域,其实就是let被作用域限定,在{}外无效
let不存在变量提升,不允许先使用后声明
let不影响作用域链

const

声明常量
潜规则:一般常量用大写
同样是块级作用域
对数组和对象的元素修改,不算做对常量的修改,不会报错

const TEAM =['a','b','c']//地址没变
TEAM.push('d')

解构赋值

ES6允许按照一定模式从数组和对象提取值,对变量进行赋值

1.数组的解构

const F=['1','2','3'];
let [f,s,t]=F;
//因为是数组所以用[]

2.对象的解构

const superxmy={
	name:'superxmy',
	age:'你猜',
	listen:function(){
		console.log("vocaloid")
	}
}
let {name,age,listen}=superxmy;//相当于我们声明了3个变量并进行了赋值
//因为是对象所以用{}

模板字符串

ES6新增了声明字符串的方式,反引号,以及${},用于解构

let str=`一个字符串`
//内容中可以直接出现换行符
let s=`<ul>
		<li>1<li>
		<li>2<li>
       </ul>`


//可以直接进行变量拼接
let nihao='nihao'
let xiexie=`xiexie`
let old =nihao+'xiexie'//老方法
let neww =`${nihao}xiexie`

//固定写法${},非常重要

对象的简化写法

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

let name='superxmy'
let change=function(){
    console.log('change')
}

const school={
    name,
    change,
    improve(){
        console.log("不愧是我")
    }
}
//上面的代码可以等效为
const school={
    name:name,
    change:change,
    improve:function(){
        console.log("不愧是我")
    }
}

箭头函数

ES6允许使用箭头(=>)定义函数

let fn1=function(){}

let fn2=(a,b)=>{
    return a+b
}
let result = fn2(1,2)

this是静态的,this始终指向函数声明时所在作用域下的this的值

function getName(){
    console.log(this.name)
}
let getName2=()=>{
    console.log(this.name)
}

//设置window对象的name属性
window.name='superxmy'
const school={
    name:"xmy"
}
//直接调用
getName();//输出superxmy
getName2();//输出superxmy
//call方法调用
getName.call(school);//老的会发生改变,指向school
getName2.call(school);//箭头不会改变,依然指向window

不能作为构造函数实例化对象

//-------------------------会报错
let Person=(name,age)=>{
    this.name=name;
    this.age=age
}
let me=new Person('superxmy',999);
console.log(me)
//--------------------------会报错

不能使用arguments 变量

//--------------------------会报错
let fn=()=>{
    console.log(arguments);
}
fn(1,2,3);
//--------------------------会报错

箭头函数的简写

当形参有且只有一个时可以简写

let add=n=>{
	return n+n
}

代码只有一条语句的时候,可以省略花括号,且return必须省略,此时语句执行结果就是返回值
let pow= n => n * n

ES6形参初始值

具有默认值的参数,一般位置要靠后(潜规则,不像c++必定)

function add(a,b,c=10){
	return a+b+c;
}

与解构赋值结合,也可以赋初始值

function connect({host="127.0.0.1",username,password,port}){
	console.log(host)
}
connect({
	host:'localhost',
	username:'root',
	password:'123456'
	port:3306
})

rest参数

ES6引入rest参数,用于获取函数的实参,代替arguments

//ES5
function date(){
	console.log(arguments)
}
date('1','2')

//ES6
function date(...args){
    console.log(args)  //可以使用数组的方法 every map等
}
date('1','2')

rest参数必须放到参数最后

拓展运算符

拓展运算符将数组转换为逗号分隔的参数序列

const shuzu=['1','2','3']
function hanshu(){
    console.log(arguments)
}
hanshu(...shuzu)//hanshu('1','2','3')
//数组的合并
const a=['1','3','5'];
const b=['2','4','6'];
const c=[...a,...b];

//数组的克隆
const d=['1','2','3'];
const e=[...d];//提前说,是浅拷贝

//将伪数组转换为真数组
const divs=document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);

Symbol数据类型

类似于字符串的数据类型,
Symbol值是唯一的,用来结局命名冲突问题
Symbol值不饿能与其他数据进行运算
Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownkeys来获取对象的所有键名

//创建Symbol
let s =Symbol();
console.log(s,typeof s);

let s2=Symbol('superxmy');//这里的superxmy只是一个标志
let s3=Symbol('superxmy');
console.log(s2===s3)//输出false,尽管标志一样,但编号不一样

//Symbol.for创建
let s4=Symbol.for('superxmy');//此时的Symbol是个对象,我们可以称为函数对象
let s5=Symbol.for('superxmy');
console.log(s4===s5)//输出true

//不能与其他数据进行运算,也不能和自己运算

迭代器

迭代器(iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以遍历操作。
ES6创造了一种新的便利命令,for…of循环,Iterator接口主要用于for…of
原生具备iterator接口的数据(可用for of便利)
Array Arguments Set Map String TypedArray NodeList

const Name=['ni','wo','ta'];
for(let i of Name){
    console.log(v);//输出 ni wo ta
}
for(let i in Name){
    console.log(v);//输出 0 1 2
}

for…in循环前面保存的是键名,而for…of循环保存的是键值
其工作原理

  1. 创建一个指针对象,指向当前数据结构的起始位置
  2. 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
  3. 接下来不断调用next方法,指针一直往后移动,知道指向最后一个成员
  4. 每调用next方法返回一个包含value的done属性的对象

自定义遍历数据

//----------------会报错
//声明一个对象
const banji={
    name:"wobudao",
    stus:[
        'xiaoming',
        'xiaohong',
        'xiaozhang'
    ]
}
//便利数组
for(let v of banji){
    console.log(v);
}
//------------会报错

这样写的话会报错,我们的需求是遍历stus里面的成员

//声明一个对象
const banji={
    name:"wobudao",
    stus:[
        'xiaoming',
        'xiaohong',
        'xiaozhang'
    ],
    [Symbol.iterator](){
        //索引变量
        let index=0
        return {
            next:()=>{
                if(index<this.stus.length){
                    const result = {value:this.stus[index],done:false}
                    index++
                    return result
                }else{
                    return{value:undefined,done:true}
                }
                
            }
        }
    }
}
//便利数组
for(let v of banji){
    console.log(v);
}

生成器

生成器是ES6提供的一种异步编程解决方案,语法与传统函数完全不同
生成器是一种特殊的函数

function * gen(){//需要在function和函数名之间加一个*
	console.log("hello")	
}

let iterator=gen()
console.log(iterator)//这样会打印一个对象,且定义时并不会调用函数中的内容
iterator.next()   //只有使用next才会调用,并且执行gen函数中的内容

生成器函数实例

1s后输出111 2s后输出222 3s后输出333
简单方法

setTimeout(()=>{
    console.log(111)
    setTimeout(()=>{
        console.log(222)
        setTimeout(()=>{
            console.log(333)
        },3000)
    },2000)
},1000)

这种事件我们称为回调地狱

那么我们就可以用生成器函数

function one(){
    setTimeout(()=>{
        console.log(111)
        iterator.next()
    },1000)
}
function two(){
    setTimeout(()=>{
        console.log(222)
        iterator.next()
    },2000)
}
function three(){
    setTimeout(()=>{
        console.log(333)
        iterator.next()
    },3000)
}

function * gen(){
    yield one()
    yield two()
    yield three()
}
//调用生成器函数
let iterator = gen()
iterator.next()

用于模拟获取数据
先获取用户数据,在获取订单数据,在获取商品数据(伪代码)

function getUsers(){
	setTimeout(()=>{
		let data='用户数据'
        //调用next方法,并将数据传入
        iterator.next(data)
	},1000)
}
function getOrders(){
    setTimeout(()=>{
        let data='订单数据'
        iterator.next(data)
    },1000)
}
function getGoods(){
    setTimeout(()=>{
        let data='商品数据'
    },1000)
}

function *gen(){
    let users = yield getUsers()
    let orders = yield getOrders()
    let goods = yield getGoods()
}

//调用生成器函数
let iterator =gen()
iterator.next()

Promise

promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取成功或失败的结果。promise接收一个函数,这个函数有两个形参(一般为resolve,reject)

const p = new Promise(function(resolve,reject){
    setTimeout(function(){
        let data = '数据'
        resolve(data)
        
        let err= '读取失败'
        reject(err)
    },1000)
})

//调用promise 的 then 方法,一般有两个函数,成功叫value,失败叫reason
p.then(function(value){
    console.log(value)
},function(reason){
    console.error(reason)
})

举例:读取文件

//ES5
//1.引入fs模块
const fs = require('fs')
//2.调用方法读取文件
fs.readFile('./resources/xxx.txt',(err,data)=>{
    //如果失败,抛出错误
    if(err) throw err
    //如果没有出错,输出
    console.log(data.toString())
})
//ES6
//1.引入fs模块
const fs = require('fs')
//3.使用promise封装
const p = new Promise(function(resolve,reject){
    fs.readFile('./resources/xxx.txt',(err,data)=>{
        //判断如果失败
        if(err) reject(err)
        //如果成功
        resolve(data)
    })
})

p.then(function(value){
    console.log(value.toString())
},function(reason){
    console.log("读取失败")
})

Promise封装Ajax

const p = new Promise((resolve,reject)=>{
  //1.创建对象
	consr xhr = new XMLHttpRequest()
	//2.初始化
	xhr.open("GET","https://api.apiopen.top/getJoke")
	//3.发送
	xhr.send()
    //4.绑定事件,处理结果
    xhr.onreadystatechange = function(){
        //判断
        if(xhr.readyState === 4){
            //判断状态码200-299
            if(xhr.status>=200 && xhr.statue<300){
                //成功
                resolve(xhr.response)
            }else{
                //失败
                reject(xhr.status)
            }
        }
    }  
})

//指定回调
p.then(function(value){
    console.log(value)
},function(reason){
    console.log(reason)
})

Promise.prototype.then

//创建promise对象
const p = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('用户数据')
    },1000)
})
//调用then方法
const result = p.then(value=>{//.then方法返回的结果是promise,但状态是由回调函数的执行结果来决定
    console.log(value)  
    return 123      //如果回调函数中返回的结果是 非promise 类型的数据,状态为成功,返回值为对象的成功的值
    return new Promise((resolve,reject)=>{//返回的是promise类型
        resolve('ok')
    })
    throw new Error('出错啦')//抛出的是Promise状态,值为抛出的值
},reason=>{
    console.warn(reason)
})

console.log(result)

then方法可以链式调用

//创建promise对象
const p = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('用户数据')
    },1000)
})
p.then(value=>{},reason=>{}).then(value=>{},reason=>{})

模块化

模块化指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。其优点有

  • 防止命名冲突
  • 代码复用
  • 高维护性

浏览器的引入方式(通用)

import * as m from "./src/js/m.js"

统一暴露

let superxmy = 'NB'
function name(){
    console.log('xmy')
}

export {superxmy,name}

引入模块

//解构赋值
import {superxmy,name} from "./src/js/m.js"
console.log(superxmy)

import {superxmy as sxmy,name} from "./src/js/m1.js"//使用别名,解决命名出错的问题
console.log(sxmy)

ES7

Array.prototype.includes

includes方法用来检测数组中是否含某个元素,返回布尔类型值

指数操作符

**,功能和Math.pow相同

ES8

async

解决异步编程的最终方案,可以让异步代码像同步代码一样
async 函数的返回值为promise对象,是成功的。如果抛出错误,那返回的是失败的promise。
promise对象的结果由async函数执行的返回值决定

async function fn(){
    return 'xmy'
}
const result =fn()
console.log(result)//状态为成功,值为xmy

await

  • await必须写在async函数中
  • await右侧的表达式一般为promise对象
  • await返回的是promise成功的值
  • await的promise失败了,就会抛出异常,需要通过try…catch捕捉获取
//创建promise对象
const p = new Promise((resolve,reject)=>{
    resolve("成功")
})

async function fn(){
    let result =await p
    console.log(result)
}
//调用函数
fn()

async和await实例

读取文件内容

//引入fs模块
const fs = require("fs")
//读取F1文件
function readF1(){
    return new Promise((resolve,reject)=>{
        fs.readFile("./resources/file1.txt",(err,data)=>{
            //如果失败
            if(err) reject(err)
            resolve(data)
        })
    })
}
//读取F2文件
function readF2(){
    return new Promise((resolve,reject)=>{
        fs.readFile("./resources/file2.txt",(err,data)=>{
            //如果失败
            if(err) reject(err)
            resolve(data)
        })
    })
}
//读取F3
function readF3(){
    return new Promise((resolve,reject)=>{
        fs.readFile("./resources/file3.txt",(err,data)=>{
            //如果失败
            if(err) reject(err)
            resolve(data)
        })
    })
}
//声明async函数
async function fn(){
    let F1 = await readF1()
    let F2 = await readF2()
    let F3 = await readF3()
}
fn()

async和await结合发送Ajax请求

这是用promise的方法封装对象

//ES6
function sendAjax(url){
    return new Promise((resolve,reject)=>{
        //创建对象
        const x =new XMLHttpRequest()
        //初始化
        x.open('GET',url)
        //发送
        x.send()
        //事件绑定
        x.onreadystatechange =function(){
            if(x.readyState === 4){
                if(x.status >= 200 && x.status < 300){
					//成功
                    resolve(x.response)
                }else{
                    //失败
                    reject(x.status)
                }
            }
        }
   })
}


sendAjax("api").then(value=>{
    console.log(value)
},reason=>{})

使用async与await

//ES8
function sendAjax(url){
    return new Promise((resolve,reject)=>{
        //创建对象
        const x =new XMLHttpRequest()
        //初始化
        x.open('GET',url)
        //发送
        x.send()
        //事件绑定
        x.onreadystatechange =function(){
            if(x.readyState === 4){
                if(x.status >= 200 && x.status < 300){
					//成功
                    resolve(x.response)
                }else{
                    //失败
                    reject(x.status)
                }
            }
        }
   })
}

async function fn(){
    //发送Ajax
    let result =await sendAjax("api")
    console.log(result)
}

Q.E.D.