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循环保存的是键值
其工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,知道指向最后一个成员
- 每调用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.