ES6性特性:
-
let和const命令
-
es6的模板字符串
-
增强的函数
-
扩展的字符串、对象、数组功能
-
解构赋值
-
Symbol
-
Map和Set
-
迭代器和生成器
-
Promise对象
-
Proxy对象
-
async的用法
-
类class
-
模块化
强大的babel: 针对10%的浏览器对es6的不支持,需要前端的某些工具来对他进行转换,被称为下一代js编译器
let\const
-
块级作用域、不存在变量提升、不允许重复声明,不会污染全局作用域
-
const声明常量,一旦被声明,无法修改
-
在默认情况下用const,而只有你在知道变量值需要被修改的情况下使用let
模板字符串
使用tab键上面的反引号``,使用变量时使用${变量名}
强大的函数
这是ES5写法
函数内部有一个属性对象叫arguments
<script>
function pick(obj) {
let result = Object.create(null)
for (let i = 1; i < arguments.length; i++) {
result[arguments[i]] = obj[arguments[i]]
}
return result
}
let book = {
title: 'es',
author: '小马',
year: 2021
}
let bookData = pick(book, 'title', 'year')
console.log(bookData)
</script>
ES6:
剩余参数:由三个点...和一个紧跟着的具名参数指定 ...keys
<script>
function pick(obj,...keys) {
//...keys解决了arguments问题
console.log(keys);
let result = Object.create(null);//创建一个空对象
for(let i=0;i<keys.length;i++){
result[keys[i]] = obj[keys[i]];
}
return result;
}
let book = {
title: 'es',
author: '小马',
year: 2021
}
let bookData = pick(book, 'author', 'year')
console.log(bookData)
</script>
function checkArgs(...args){
console.log(args)
}
checkArgs('a','b','c')
扩展运算符...(跟剩余参数对应起来的还有这个)
剩余参数:把多个独立的合并到一个数组中
扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数
-
剩余运算符:把多个独立的合并到一个数组中(一般放在函数形参上使用)
-
扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数(针对某个数组对他进行分割,作为分离的参数,对函数进行传递)
Math.max() 函数返回一组数中的最大值
const maxNum = Math.max(20,30) console.log(maxNum)
(es5写法)处理数组中的最大值,使用apply
const arr = [10,20,30,90,100,40] console.log(Math.max.apply(null,arr))
(es6写法)扩展运算算法更方便
const arr =[10,20,30,90,100,40]; console.log(Math.max(...arr))
箭头函数
使用=>来定义,function(){} 等于与 ()=>{}
es5中this指向:取决于调用该函数的上下文对象
es6中的箭头函数没有this指向问题,箭头函数内部this值只能通过查找作用域链来确定,一旦使用箭头函数,当前就不存在作用域链
let add = function(a,b){ return a+b } let add =(a,b)=>{ resturn a+b } console.log(add(10,20)) 简便写法: //如果只返回一个形参 let add =val => val console.log(add(10)) //如果两个形参 let add =(val1,val2) => val + val2; console.log(add(10,20)) let getObj =id => ({id:id,name:"小马哥"})//这是个小括号一个表达式,内部返回一个对象 //闭包 let fn =(()=>{ return ()=>{ console.log('niuiu') } })() fn()
使用箭头函数的注意事项
-
使用箭头函数,函数内部没有arguments
-
箭头函数不能使用new关键字来实例化对象
-
function 函数也是一个对象,但是箭头函数不是一个对象,他其实就是一个语法糖(函数的语法糖,但他不是一个对象)
解构赋值
解构赋值是对赋值运算符的一种扩展
他针对数组和对象进行操作
优点:代码书写上简洁易读
1.对对象的结构
-
let node ={
type:'iden',
name:'foo'
}
es5写法:
//let type = node.type
//let name = node.name
es6写法:
//完全解构
let{type,name} =node
console.log(type,name)
___________________________________________________
let obj ={
a:{
name:"张三"
},
b:[],
c:'hello,world'
}
//不完全解构,可忽略某些属性
let {a} = obj//花括号里的名字,一定是当前对象中的属性名
console.log(a)
//可用剩余运算符
let{a,...res} =obj
console.log(res)
//对对象的解构
let {a,b=30} ={a:20}
2.对数组的解构
let arr =[1,2,3]
let [a,b,c] =arr
console.log(a,b,c)
//可嵌套
let [a,[b],c] =[1,[2],3]
扩展对象的功能
es6直接写入变量和函数,作为1对象的属性和方法
const name ='小昂额',
age =20;
const person ={
name:name,
age:age,
sayName:function(){
}
}
//对于上面这种写法es6中可以发生简写的写法
const name ='小昂额',
age =20;
const person ={
name,//等价于name:name,注意属性名和属性值一定是一样的才能用这种简写形式
age,
sayName(){
console.log(this.name)
}
}
person.sayName()
———————————————————————————————————————————————————
let cart ={
wheel:4,
set(newValue){
if(neValue < this.wheel){
throw new Error('轮子太少')
}
this.wheel = newVal
},
get(){
return this.wheel;
}
}
//console.log(cart.get())
cart.set(3)
console.log(cart.get())
———————————————————————————————————————————————————
const obj ={};
obj.isShow = true;
const name = 'a';
//给obj对象添加属性abc,abc又依赖于name
obj[name + 'bc'] = 123;//这是一个属性表达式,用表达式来进行组合
obj['f'+'bc'] =function(){
console.log(this)
}
console.log(obj)
可以写成这样子:
const name ='a';
const obj ={
isShow:true,
[name+'bc']:123,
['f'+name](){
console.log(this)
}
}
console.log(obj)
对象的方法
is() 等价于 ===:比较两个值是否严格相等
console.log(NaN===NaN)//false,===号的缺陷,特殊性is()解决了这个问题,一般用===较多 console.log(Object.is(NaN,NaN))//true
assign():对象的合并,返回合并之后的新对象
Object.assign(target,obj1,obj2...)//target目标对象,他就会把当前的obj1,obj2...所有对象中的属性,都合并放进target对象中
//当调用Object.assign把当前对象中的属性{a:1},{b:2},合并到空对象{} let newObj = Object.assign({},{a:1},{b:2}); console.log(newObj)
原始数据类型Symbol
他表示独一无二
最大的用途:用来定义对象的私有变量
const name = Symbol('name');
const name2 = Symbol('name');
console.log(name===name2)
let s1 = Symbol('s1');
console.log(s1);
let obj ={
[s1]:'小马哥'
};
//如果用Symbol定义的对象中的变量,取值时一定要用[变量名]
console.log(obj[s1])
Map和Set
Set集合:表示无重复值得有序列表
let set = new Set() console.log(set) //添加元素,没有重复值 set.add(2)//数值 set.add(‘4’)//字符串 set.add(‘4’) set.add([1,2,3])//数组 //删除元素 set.delete(2) //校验某个值是否在set中 console.log(set.has('4')) //访问集合的长度 console.log(set.size) //将set转换成数组 let set2 = new Set([1,2,3,3,3,4]); //扩展运算符 let arr =[...set2]; console.log(arr)
Map类型是键值对的有序列表,键和值是任意类型
let map = new Map() //添加 map.set('name','张三宝'); map.set('age','桌') //获取 console.log(map.get('name')) //校验 map.has('name')//true //删除 map.delete('name') //全部清除 map.clear()
数组的扩展功能
数组的方法 from() of()
1.from()
将伪数组转换成真正的数组,比如arguments对象
function add(){ let arr = Array.from(arguments); console.log(arr) } add(1,2,3)
扩展运算符 将伪数组转换成正真的数组
let lis = document.querySelectorAll('li') console.log([...lis])
from()还可以接受第二个参数,用来对每个元素进行处理
let liContents = Array.from(lis,ele => ele.textContent)//ele代表每一个小li,ele.textContent是返回值,将li的文本返回出来 console.log(liContents)
2.of()
将任意的数据类型,转换成数组
console.log(Array.of(3,11,20,[1,2,3],{id:1}))
3.copywithin()
数组内部将制定位置的元素复制到其他的位置,返回当前数组
console.log([1,2,3,8,9,10].copyWithin(0,3))//从3位置往后的所有值都复制,替换从0位置往后的值 ///[8,9,10,8,9,10]
4.find() 找出第一个符合条件的数组成员
let num = [1,2,-10,-20,9,2].find(n => n<0)//找出数组小于0的数 console.log(num)
findIndex()找出第一个符合条件的数组成员的索引
let numIndex = [1,2,-10,-20,9,2].findIndex(n => n<0)//找出数组小于0的数 console.log(numIndex)
5.entries() keys() values() 返回一个遍历器 可以使用for...of循环进行遍历
1.keys()对键名遍历
2.values()对值遍历
3.entries()对键值对遍历
//取索引 for(let index of ['a','b'].keys()){ console.log(index) } //取值 for(let ele of ['a','b'].value()){ console.log(ele) } //索引值对应相应的值,键值对 for(let [index,ele] of ['a','b'].entries()){ console.log(index,ele) } //每next()一个就放行一个 let letter =['a','b','c']; let it = letter.entries(); //如果数组中的元素超出边界就返回undefined console.log(it.next().value)//0,"a" console.log(it.next().value)//1,"b" console.log(it.next().value)//2,"c"
6.includes()返回一个布尔值,表示某个数组是否包含给定的值
console.log([1,2,3].includes(2))
解决之前indexOf()检查某个数组是否包含给定的值,有就返回1,没有返回-1
迭代器:Iterator
是一种新的遍历机制
两个核心:
1.迭代器是一个接口,能快捷的访问数据,通过Symbol.iterator来创建迭代器,通过迭代器的next()获取迭代之后的结果
2.迭代器是用于遍历数据结构的指针(数据库的游标)
使用迭代 (迭代器就是遍历器,遍历器就是迭代器)
const items = ['one','two','three']; //1.创建新的迭代器 const ite = items[Symbol.iterator](); console.log(ite.next())//{value:"one",done:false}done如果为false表示遍历继续,如果为true表示遍历完成 console.log(ite.next()) console.log(ite.next()) console.log(ite.next())
生成器和迭代器通常紧密相关
生成器(generator函数,yield关键字)
generator函数,可以通过yield关键字,将函数挂起,为了改变执行流程提供了可能,同时为了做异步编程提供了方案
他与普通函数的区别
1.function后面 函数名之前有个*
2.只能在函数内部使用yield表达式,让函数挂起
function* func(){
yield 2;
}
//返回一个遍历器对象。可以调用next()
let fn = func()
console.log(fn.next())
总结:generator函数是分段执行的,yield语句是暂停执行,而next()恢复执行,(一个next()对应一个yield)
function* add(){
console.log('start');
//x可真的不是yield ’2‘的返回值,他是next()调用 恢复当前yield()执行传入的实参
let x = yield '2';
console.log('one:'+x);
let y=yield '3';
console.log('two:'+y);
return x+y
}
const fn = add();
console.log(fn.next())//{value:'2',done:false}
console.log(fn.next(20))//{value:'3',done:false}
console.log(fn.next(30))//{value:50,done:true}
使用场景:为不具备Interator接口对象提供了遍历操作
function* objectEntries(obj){
//获取对象的所有的key保存到数组[name,age]
const propKeys = Object.keys(obj)
for(const propkey of propKeys){
yield [propkey,obj[propkey]]
}
}
const obj ={
name:'小马哥',
age:18
}
obj[Symbol.iterator] = objectEntries;
console.log(obj);
for(let [key,value] of objectEntries(obj)){
console.log(`${key}:${value }`)
}
Generator的应用:作用:部署ajax操作,让异步代码同步化
模仿加载请求数据页面异步操作
<script>
//加载loading..页面
//数据加载完成考虑...(异步操作)
// loading关闭掉
//构造一个生成器
function* load() {
loadUI()
yield showData()//卡在这个位置
hideUI()
}
let itLoad = load();//把迭代器创建出来
itLoad.next();//执行showData()
function loadUI() {
console.log('加载loading..页面')
}
function showData() {
//模拟异步操作
setTimeout(() => {
console.log('数据加载完成...');
itLoad.next()//通过迭代器,继续让他往下执行hideUI()
}, 1000)
}
function hideUI() {
console.log('隐藏loading...页面')
}
</script>
Promise 承诺
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果
各种异步操作都可以用同样的方法进行处理 axios
特点:
-
对象的状态不受外界影响,处理异步操作 ,三个状态:Pending(进行中)、Resolved(成功,已完成,你成功回调的结果已存储到我们当前的对象容器中)、Rejected(失败)
-
一旦状态改变,就不会再变,任何时候都可以得到这个结果
<script>
let pro = new Promise(function(resolved,rejected){
//执行异步操作
let res = {
code:200,
data:{
name:'小马哥'
},
error:'失败了'
}
setTimeout(()=>{
if(res.code ===200){
resolved(res.data)
}else{
rejected(res.error)
}
},1000)
})
console.log(pro);
pro.then((val)=>{
console.log(val)
},(err)=>{
console.log(err)
})
</script>
//以上写法可以改成下面这样子 //秒数由我们自己在外界控制
//封装
<script>
function timeOut(ms){
return new Promise((resolved,rejected)=>{
setTimeout(()=>{
resolved('hello promise success!!')
},ms)
})
}
timeOut(2000).then((val)=>{
console.log(val)
})
</script>
//自己封装的ajax方法
<script>
const getJSON = function(url){
return new Promise((resolve,reject)=>{
const xhr = new XMLHttpRequest();
xhr.open('GET',url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept','application/json');
//发送
xhr.send();
function handler(){
console.log(this)
if(this.readyState ===4){
if(this.status === 200){
resolve(this.response)
}else{
reject(new Error(this.statusText))
}
}
}
})
}
getJSON('https://www.apiopen.top/weatherApi?city=成都')
.then((data)=>{
console.log(data)
},(error) =>{
console.log(error)
}) ________________________________________________________
getJSON('https://www.apiopen.top/weatherApi?city=成都')
.then(data=>{//捕获成功
console.log(data)
},catch(err=>{//捕获异常
console.log(err)
})
</script>
then()方法
then() 第一个参数是resolve回调函数 ,第二个参数是可选的,是reject状态回调函数
then()返回一个新的promise实例,可以采用链式编程
resolve() reject() all() race() done() finally()
resolve()能将现有的任何对象转换成promise对象,reject()方法也是一样的
// let p = Promise.resolve('foo'); //等价于下面这个 let p = new Promise(resolve=>resolve('foo')) console.log(p); p.then((data)=>{ console.log(data) })
all()
应用:一些游戏类的素材比较多,等待图片、flash、静态资源文件都加载完成才进行页面的初始化
<script>
let promise1 = new Promise((resolve,reject)=>{});
let promise2 = new Promise((resolve,reject)=>{});
let promise3 = new Promise((resolve,reject)=>{});
let p4 = Promise.all([promise1,promise2,promise3])
p4.then(()=>{
//三个都成功,才成功
}).catch(err=>{
//如果有一个失败,则失败
})
</script>
race()
某个异步请求设置超时时间,并且在超时后执行相应的操作
function requestImg(imgSrc){
return new Promise((resolve,reject)=>{
const img = new Image();
img.onload = function(){
resolve(img)
}
img.src=imgSrc
})
}
function timeout() {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(new Error('图片请求超时'))
},1000)
})
}
Promise.race([requestImg('此处放图片地址'),timeout()]).then(data=>{
console.log(data)
document.body.appendChild(data)
}).catch(err=>{
console.log(err)
})
async异步操作
作用:使得异步操作更加方便
基本操作:async他会返回一个Promise对象 then catch
async是Generator的一个语法糖
如果async函数中有多个await ,那么then函数会等待所有的await指令 运行完的结果,才去执行
async function f(){ // return await 'hello async'; let s = await 'hello world'; let data = await s.split(''); return data } f().then(v=>{console.log(v)})
需求:向获取和风天气,现在now的数据
const getJSON = function(url){
return new Promise((resolve,reject)=>{
const xhr = new XMLHttpRequest();
xhr.open('GET',url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept','application/json');
//发送
xhr.send();
function handler(){
console.log(this)
if(this.readyState ===4){
if(this.status === 200){
resolve(this.response)
}else{
reject(new Error(this.statusText))
}
}
}
})
}
async function getNowWeather(url){
//发送ajax 获取实况的天气
let res = await getJSON(url)
console.log(res);
//获取HeWeather6的数据,获取未来3~7天的天气状况
let arr = await res.HeWeather6
return arr[0].now
}
getNowWeather('https://')
.then(now=>{
console.log(now)
})xxxxxxxxxx async function const getJSON = function(url){ return new Promise((resolve,reject)=>{ const xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.onreadystatechange = handler; xhr.responseType = 'json'; xhr.setRequestHeader('Accept','application/json'); //发送 xhr.send(); function handler(){ console.log(this) if(this.readyState ===4){ if(this.status === 200){ resolve(this.response) }else{ reject(new Error(this.statusText)) } } } }) } async function getNowWeather(url){ //发送ajax 获取实况的天气 let res = await getJSON(url) console.log(res); //获取HeWeather6的数据,获取未来3~7天的天气状况 let arr = await res.HeWeather6 return arr[0].now } getNowWeather('https://') .then(now=>{ console.log(now) })
Generator Promise async 1.解决回调地狱问题 2.使得异步操作更加方便
class类
<script>
// // es5造类
// function Person(name,age){
// this.name = name;
// this.age = age;
// }
// Person.prototype.sayName = function(){
// return this.name
// }
// let p1 = new Person('小马',20);
// console.log(p1)
—————————————————————————————————————————————————————————
// es6
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
sayName(){
return this.name
}
syaAge(){
return this.age
}
}
let p1 = new Person('小马',20)
console.log(p1)
</script>
类的继承
<script>
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
return this.name;
}
sayAge() {
return this.age
}
}
class Dog extends Animal {
constructor(name,age,color){
super(name, age);//继承父类
this.color = color;
}
//子类自己的方法
sayColor(){
return `${this.name}是${this.age}岁了,它的颜色是${this.color}`
}
//重写父类的方法
sayName(){
return this.name +super.sayAge()+this.color
}
}
let d1 = new Dog('小黄',20,'red')
console.log(d1.sayColor())
console.log(d1.sayName())
</script>
思考:如何让多个类,混入到一个类中
module模块的使用
-
es6模块模块功能主要有两个命令构成:export(抛出)和import(导入)
-
export用于规定模块的对外接口 import用于输入其他模块提供的功能
modules/index.js
export const name ="张三";
export const age =18;
export function sayName(){
return 'my name'
}
module模块的使用.html
<script type="module">
import {name,age,sayName} from './modules/index.js'
console.log(name,age,sayName())
</script>