一、为什么要学习ES6?
1.1.ES5语言的先天性不足。比如变量提升、内置对象的方法不灵活、模块化实现不完善等等
1.2.为了后面vue、尤其是react框架做好了准备
1.3.目前大部分公司的项目都在使用es6
二、ES6新特性
2.1.let和const命令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>let和const</title>
</head>
<body>
<script>
// var
// var a = 2
//1.let声明变量,没有变量提升
// console.log(a);
// let a = 10;
// console.log(b); //报错,不会打印结果
// 2.是一个块作用域
// if(1===1){
// let b = 10;
// }
// 3.let不能被重复声明
// let a = 1;
// let a = 3;
// console.log(a);
//const 声明常量 一旦被声明 无法修改
//块作用域
//不能被重复声明
// const max = 30;
// max = 40;
// console.log(max); //网页控制台报错
// const person = {
// name:"1900"
// }
// // 网页控制台报错 不能修改里面的变量,可以修改变量值
// // person = {
// // age:20
// // }
// person.name = "alex";
// console.log(person);
//作用1:for循环解决问题
// const arr = []
// for(let i = 0;i<10;i++){
// arr[i] = function(){
// return i;
// }
// }
// // console.log(arr);
// console.log(arr[5]());
//作用2:不会污染全局变量
let RegExp = 10;
console.log(RegExp);
console.log(window.RegExp);
//建议:在默认情况下,用const,而只有在你知道变量值需要被修改的情况使用let
</script>
</body>
</html>
2.2.es6的模板字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板字符串</title>
</head>
<body>
<div class="box">
</div>
<script>
//模板字符串:使用tab键上面的反引号``,插入变量时使用${变量名}
const oBox = document.querySelector('.box');
let id = 1,name = 1900;
let htmlStr = `<ul>
<li>
<p id=${id}>${name}</p>
</li>
</ul>`;
// oBox.innerHTML = "<ul><li><p id="+id+">"+name+"</p></li></ul>"
oBox.innerHTML = htmlStr;
</script>
</body>
</html>
2.3.增强的函数
<script>
//1.带参数默认值的函数
// ES5的写法
// function add(a,b){
// a = a || 10;
// b = b || 20;
// return a + b;
// }
// console.log(add());
//ES6
// function add (a = 10, b = 20){
// return a + b;
// }
// console.log(add(30));
//2.默认的表达式也可以是一个函数
// function add (a, b = getVal(5)){
// return a + b;
// }
// function getVal(val){
// return val + 5;
// }
// console.log(add(10));
//ES5的写法
// 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:'ES6',
// author:'1900',
// year:2024
// }
// let bookData = pick(book,'title','author','year');
// console.log(bookData);
// 3.ES6的写法 剩余参数:由三个点..和一个紧跟看的具名参数指定...keys
function pick(obj, ...keys){
//...keys 解决了argumentsde的问题
let result = Object.create(null);
for(let i = 0; i<keys.length;i++){
result[keys[i]] = obj[keys[i]];
}
return result;
}
let book = {
title:'ES6',
author:'1900',
year:2024
}
let bookData = pick(book,'author','year');
console.log(bookData);
//4.扩展运算符 ...
//剩余运算符 :把多个独立的参数合并到一个数组中
//扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数
// const maxNum = Math.max(20,30);
// console.log(maxNum);
//处理数组中的最大值,使用apply
const arr = [10,20,50,30,90,100,40];
// console.log(Math.max.apply(null,arr))
//es6扩展运算符
console.log(Math.max(...arr));
// es6箭头函数
//使用=>来定义 function(){}等于()=>{}
// let add = function(){
// return a + b;
// }
// let add = (a,b) =>{
// return a + b;
// }
// let add = (val1,val2) => val1 + val2;
// console.log(add(10,20));
// let fn = ()=>'hello world' + 123;
// console.log(fn());
//没有this绑定
// es5中this指向 取决于调用该函数的上下文对象
// let PageHandle = {
// id:123,
// init:function(){
// document.addEventListener('click',function(event){
// this.doSomeThings(event.type);
// })
// },
// doSomeThings:function(type){
// console.log(`事件类型:${type},当前id:${this.id}`);
// }
// }
// PageHandle.init();
//es6中
let PageHandle = {
id:123,
init:function(){
// 箭头函数没有this指向,箭头函数内部this值只能通过查找作用域链来确定,一旦使用箭头函数,当前就不存在作用域
document.addEventListener('click',(event)=>{
this.doSomeThings(event.type);
},false)
},
doSomeThings:function(type){
console.log(`事件类型:${type},当前id:${this.id}`);
}
}
PageHandle.init();
//使用箭头函数的注意事项1:使用箭头函数 函数内部没有arguments
let getVal = (a,b)=>{
console.log(arguments);
return a + b;
}
console.log(getVal(1,3));
//2.箭头函数不能使用new关键字实例化对象
let Person = ()=>{
};
// function函数 也是一个对象,但是箭头函数不是一个对象,它其实就是一个语法糖
let p = new Person();
</script>
2.4.扩展的字符串、对象、数组功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>扩展的对象的功能</title>
</head>
<body>
<script>
//es6直接写入变量和函数,作为对象的属性和方法
// const name = '1900',age = 20;
// const person = {
// name,//等价于name:name
// age,
// sayName(){
// console.log(this.name);
// }
// }
// person.sayName();
// function fn(x,y){
// return{x,y};
// }
// console.log((10,20));
// let cart = {
// wheel:4,
// set(newVal){
// if(newVal < 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[name+'bc'] = 123;
// // console.log(obj);
// 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
console.log(Object.is(NaN,NaN));//true
//assign()
//对象的合并
//object.assign(target,obj1,obj2....)
//返回合并之后的新对象
let newObj = Object.assign({},{a:1},{b:2});
console.log(newObj);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>数组的扩展功能</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
//数组的方法 from() of()
//from() 将伪数组转换成真正的数组
function add(){
console.log(arguments);
//es5转换
// let arr = [].slice.call(arguments);
// console.log(arr);
//es6
let arr = Array.from(arguments);
console.log(arr);
}
add(1,2,3);
let lis = document.querySelectorAll('li');
// console.log(lis);
// console.log(Array.from(lis));
//扩展运算符 将伪数组转换成真正的数组
console.log([...lis]);
//from()还可以接受第二个参数,用来对每个元素进行处理
let liContents = Array.from(lis,ele => ele.textContent);
console.log(liContents);
//2.of() 将任意的数据类型,转换成数组
console.log(Array.of(3,11,20,[1,2,3],{id:1}));
//3.copywithin() 将数组内部指定位置的元素复制到其它的位置,返回当前数组
//从3位置往后的所有数组,替换从0位置往后的三个数值
console.log([1,2,3,8,9,10].copyWithin(0,3)); //[8,9,10,8,9,10]
//4.find() findIndex()
//find()找出第一个符合条件的数组成员
let num = [1,2,-10,-20,9,2].find(n => n < 0);
console.log(num);
//findIndex()找出第一个符合条件的数组成员的索引
let numIndex = [1,2,-10,-20,9,2].findIndex(n => n < 0);
console.log(numIndex);
//5.entries() keys() values() 返回一个遍历器 可以使用for...of循环进行遍历
//keys()对键名的遍历
//values()对值的遍历
//entries()对键值对的遍历
console.log(['a','b'].keys());
for(let index of ['a','b'].keys()){
console.log(index);
}
for(let ele of ['a','b'].values()){
console.log(ele);
}
for(let [index,ele] of ['a','b'].entries()){
console.log(index,ele);
}
let letter = ['a','b','c']
let it = letter.entries();
// console.log(it.next().value);
// console.log(it.next().value);
// console.log(it.next().value);
//6.includes()返回一个布尔值,表示某个数组是否包含给定的值
console.log([1,2,3].includes(2));
console.log([1,2,3].includes(4));
//之前indexof()
console.log([1,2,3].indexOf('2'));
</script>
</body>
</html>
2.5.解构赋值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>解构赋值</title>
</head>
<body>
<script>
// 解构赋值是对赋值运算符的一种扩展
//它针对数组和对象来进行操作
//优点:代码书写上简洁易懂
let node = {
type:'iden',
name:'foo'
}
// let type = node.type;
// let name = node.name;
//完全解构
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};
//对数组完全解构
// let arr = [1,2,3];
// let [a,b,c] = arr;
// console.log(a,b,c);
//可嵌套
let [a,[b],c] = [1,[2],3];
</script>
</body>
</html>
2.6.Symbol
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Symbol</title>
</head>
<body>
<script>
//原始数据类型 Symbol,它表示是独一无二的值
//最大的用途:用来定义对象的私有变量
const name = Symbol('name');
const name2 = Symbol('name');
console.log(name === name2);
let s1 = Symbol('s1');
console.log(s1);
let obj = {
[s1]:'1900'
};
// obj[s1] = '1900';
//如果用Symbol定义的对象中的变量,取值时一定要用[变量名]
console.log(obj[s1]);
// for(let key in obj){
// console.log(key);
// }
// console.log(Object.keys(obj));
//获取Symbol声明的属性名(作为对象的key)
// let s = Object.getOwnPropertySymbols(obj);
// console.log(s[0]);
let m = Reflect.ownKeys(obj);
console.log(m);
</script>
</body>
</html>
2.7.Map和Set
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Map和Set</title>
</head>
<body>
<script>
//集合:表示无重复值的有序列表
let set = new Set();
console.log(set);
//添加元素
set.add(2);
set.add('4');
set.add(2);
set.add([1,2,3]);
//删除元素
set.delete(2);
//校验某个值是否在set中
console.log(set.has('4'));
console.log(set.size);
// set.forEach((val,key)=>{
// console.log(val);
// console.log(key);
// })
//将set转换成数组
let set2 = new Set([1,2,3,3,3,4]);
//扩展运算符操作
let arr = [...set2]
console.log(arr);
//1.set中对象的引用无法被释放
// let set3 = new Set(),obj = {};
// set3.add(obj);
// //释放当前的资源
// obj = null;
// console.log(set3);
let set4 = new WeakSet(),obj = {};
set4.add(obj);
//释放当前的资源
obj = null;
console.log(set4);
// WeakSet
//1.不能传入非对象类型的参数
//2.不可迭代
//3.没有forEach()
//4.没有size属性
//Map类型是键值对的有序列表,键和值是任意类型
// let map = new Map();
// map.set('name','张三');
// map.set('age',20);
// console.log(map.get('name'));
// console.log(map);
// map.has('name');//true
// map.delete('name');
// console.log(map);
// map.clear();
// console.log(map);
// map.set(['a',[1,2,3,]],'hello');
// console.log(map);
let m = new Map([
['a',1],
['c',2]
]);
console.log(m);
</script>
</body>
</html>
2.8.选代器和生成器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>迭代器</title>
</head>
<body>
<script>
// iterator
// es6 引入的遍历机制,两个核心
// 1.迭代器是一个接口,能快捷的访问数据,通过Symbol.iterator来创建迭代器,通过next方法获取下一个数据
//2.迭代器是用于遍历数据结构的指针
const item = ['one','two','three']
// 1.创建新的迭代器
const ite = items[Symbol.iterator]();
console.log(ite.next());//{value : "one",done:false} fasle 遍历未完成
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>生成器</title>
</head>
<body>
<script>
// generator函数,可以通过yield关键字,将函数挂起,为了改变执行流提供了可能,同时为了做异步编程提供了方案
// 与普通函数的区别
//1. function后面,函数名之前有给*
//2. 只能在函数内部使用yield表达式,让函数挂起
// function* func(a){
// yield a;
// }
// //返回一个遍历器对象 可以调用next方法
// let fn = func(2);
// //console.log(o)
// console.log(fn.next());
// 总结:generator函数 分段执行的,yield语句是暂停执行 而next()恢复执行
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;
}
let 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}
//使用场景1:为不具备Interator接口的对象提供了遍历操作
function* objectEntries(){
//获取对象的所有的key保存到数组中
const propKeys = Object.keys(obj);
for(const propkey of propKeys){
yield [propkey,obj[propkey]]
}
}
const obj = {
name:'1900',
age:21
}
obj[Symbol.iterator] = objectEntries;
for(let [key,value] of objectEntries(obj)){
console.log(`${key}:${value}`);
}
</script>
</body>
</html>
2.9.Promise对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Promise</title>
</head>
<body>
<script type="module">
function timeOut(ms){
// Promise对象是一个构造函数,用来生成Promise实例
return new Promise((resolve, reject) => { // 闭包函数:一个函数里面返回一个函数
// ... 模拟执行异步操作,后端返回的数据
let res = {
// code: 200,
code: 201,
data:{
name: '牛肉粉'
},
error: '失败了'
}
setTimeout(() => {
// 异步执行成功
if (res.code === 200){
resolve(res.data);
// 异步执行失败
} else {
reject(res.error);
}
}, ms);
});
}
// then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。
timeOut(2000).then((val) => {
// success
console.log(val); //这里的值接收的是 resolved() 的值,输出 {name: "牛肉粉"}
}, (err) => {
// failure
console.log(err); //这里的值接收的是 rejected() 的值,输出 失败了
});
//使用promise封装ajax请求
const getJson = function(url){
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.resposeType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
xhr.send();
xhr.onreadystatechange = () => {
if(this.readyState === 4){
if(this.status === 200){
resolve(this.respose);
}else{
reject(new Error(this.statusText))
}
}
}
})
}
getJson('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976').then((data) => {
console.log(data);
},(error) => {
console.log(error);
}),
// then 方法的链式调用
getJson('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976').then((data) => {
return data.HeWeather6;
},then(HeWeather6) => {
console.log(HeWeather6);
})
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
.then((json) => {
console.log(json);
}).then(null,err=>{
console.log(err);
})
//等价于
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
.then((json) => {
console.log(json);
}).catch(err=>{
console.log(err);
})
let p = Promise.resolve('foo');
//等价于let p = new Promise(resolve=>resolve('foo'));
p.then((val)=>{
console.log(val);
})
let p2 = Promise.reject(new Error('出错了'));
//等价于 let p2 = new Promise((resolve,reject)=>reject(new Error('出错了)));
p2.catch(err => {
console.log(err);
})
let pro1 = new Promise((resolve, reject) => {});
let pro2 = new Promise((resolve, reject) => {});
let pro3 = new Promise((resolve, reject) => {});
let pAll = Promise.all([pro1, pro2, pro3]);
pAll.then(() => {
// 三个都成功 才成功
}).cath(err => {
// 如果一个失败 则失败
})
// 案例:试想一个页面聊天系统,我们需要从两个不同的URL分别获得用户的的个人信息和好友列表,
// 这两个任务是可以并行执行的,用Promise.all实现如下
let meInfoPro = new Promise( (resolve, reject)=> {
// 模拟资源加载需要花费时间
setTimeout(resolve, 500, 'P1');
});
let youInfoPro = new Promise( (resolve, reject)=> {
// 模拟资源加载需要花费时间
setTimeout(resolve, 600, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([meInfoPro, youInfoPro]).then( (results)=> {
console.log(results); // 获得一个Array: ['P1', 'P2']
});
// 请求图片资源
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('图片请求超时'));
}, 3000);
});
}
// Promise.race()接受一个包含多个promise对象的数组,只要有一个完成,就执行success
// 如果3s 之内加载完成就执行 then 方法, 3s 之后还没加载完成就执行 catch 方法
Promise.race([requestImg('images/2.png'), timeout()]).then((data) => {
console.log(data);
document.body.appendChild(data);
}).catch((err) => {
console.log(err);
});
</script>
</body>
</html>
2.10.Proxy对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Promise</title>
</head>
<body>
<script type="module">
function timeOut(ms){
// Promise对象是一个构造函数,用来生成Promise实例
return new Promise((resolve, reject) => { // 闭包函数:一个函数里面返回一个函数
// ... 模拟执行异步操作,后端返回的数据
let res = {
// code: 200,
code: 201,
data:{
name: '牛肉粉'
},
error: '失败了'
}
setTimeout(() => {
// 异步执行成功
if (res.code === 200){
resolve(res.data);
// 异步执行失败
} else {
reject(res.error);
}
}, ms);
});
}
// then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。
timeOut(2000).then((val) => {
// success
console.log(val); //这里的值接收的是 resolved() 的值,输出 {name: "牛肉粉"}
}, (err) => {
// failure
console.log(err); //这里的值接收的是 rejected() 的值,输出 失败了
});
//使用promise封装ajax请求
const getJson = function(url){
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.resposeType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
xhr.send();
xhr.onreadystatechange = () => {
if(this.readyState === 4){
if(this.status === 200){
resolve(this.respose);
}else{
reject(new Error(this.statusText))
}
}
}
})
}
getJson('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976').then((data) => {
console.log(data);
},(error) => {
console.log(error);
}),
// then 方法的链式调用
getJson('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976').then((data) => {
return data.HeWeather6;
},then(HeWeather6) => {
console.log(HeWeather6);
})
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
.then((json) => {
console.log(json);
}).then(null,err=>{
console.log(err);
})
//等价于
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
.then((json) => {
console.log(json);
}).catch(err=>{
console.log(err);
})
let p = Promise.resolve('foo');
//等价于let p = new Promise(resolve=>resolve('foo'));
p.then((val)=>{
console.log(val);
})
let p2 = Promise.reject(new Error('出错了'));
//等价于 let p2 = new Promise((resolve,reject)=>reject(new Error('出错了)));
p2.catch(err => {
console.log(err);
})
let pro1 = new Promise((resolve, reject) => {});
let pro2 = new Promise((resolve, reject) => {});
let pro3 = new Promise((resolve, reject) => {});
let pAll = Promise.all([pro1, pro2, pro3]);
pAll.then(() => {
// 三个都成功 才成功
}).cath(err => {
// 如果一个失败 则失败
})
// 案例:试想一个页面聊天系统,我们需要从两个不同的URL分别获得用户的的个人信息和好友列表,
// 这两个任务是可以并行执行的,用Promise.all实现如下
let meInfoPro = new Promise( (resolve, reject)=> {
// 模拟资源加载需要花费时间
setTimeout(resolve, 500, 'P1');
});
let youInfoPro = new Promise( (resolve, reject)=> {
// 模拟资源加载需要花费时间
setTimeout(resolve, 600, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([meInfoPro, youInfoPro]).then( (results)=> {
console.log(results); // 获得一个Array: ['P1', 'P2']
});
// 请求图片资源
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('图片请求超时'));
}, 3000);
});
}
// Promise.race()接受一个包含多个promise对象的数组,只要有一个完成,就执行success
// 如果3s 之内加载完成就执行 then 方法, 3s 之后还没加载完成就执行 catch 方法
Promise.race([requestImg('images/2.png'), timeout()]).then((data) => {
console.log(data);
document.body.appendChild(data);
}).catch((err) => {
console.log(err);
});
</script>
</body>
</html>
2.11.async的用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>async的用法</title>
</head>
<body>
<script>
// Generator Promise async
// 1.解决回调地狱的问题
// 2.使得异步操作更加方便
// 作用:使异步操作更方便
// 基本操作 async它会返回一个promise对象 then catch
// async是Generator的语法糖
async function f() {
// return await 'hello async';
let s = await 'hello world';
let data = await s.split('');
return data;
}
// 如果async函数中有多个await 那么then函数会等待所有的await指令 运行完所有的结果,才会去执行
f().then(v=>{
console.log(v)
}).catch(e=>console.log(e));
async function f2() {
// throw new Error('错误');
try{
await Promise.reject('错误');
}catch(error){
}
return await Promise.resolve('hello');
}
f2().then(v=>console.log(v)).catch(e=>console.log(e));
// 需求: 想获取和风天气2
async function getNowWeather(url){
// 发送ajax
let res = await getJSON(url);
}
getNowWeather("").then(now=>{
console.log(now);
})
</script>
</body>
</html>
2.12.类class
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>class类</title>
</head>
<body>
<script>
// es5 造类
// function Person(name,age){
// this.name = name;
// this.age = age;
// }
// Person.prototype.sayNmae = function(){
// return this.name;
// }
// let p1 = new Person(1900,21);
// console.log(p1);
class Person{
//实例化的时侯会立即调用
constructor(name,age){
this.name = name;
this.age = age;
}
}
// 通过Object.assign()方法一次性向类中添加多个方法
Object.assign(Person.prototype,{
sayName(){
return this.name;
},
sayAge(){
return this.age;
}
})
let p1 = new Person(1900,21);
console.log(p1)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>类的继承</title>
</head>
<body>
<script>
// 使用关键字extends
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(2,20,'red');
console.log(d1.sayName());
console.log(d1.sayColor());
</script>
</body>
</html>
2.13.模块化实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ES6模块化实现</title>
</head>
<body>
<script type="module">
// commonJS和AMD
// ES6 module
import {name,age,sayName} from '/es6/index.js';
console.log(name,age,sayName());
</script>
</body>
</html>
以上代码整合在ES6代码练习: ES6的学习,基于阮一峰的ES6文档学习和练习 (gitee.com)此地址
三、浏览器支持
各大浏览器的最新版本,对ES6的支持可以查看kangax.github.io/compat-table/es6/。随着时间的推移,支持度已经越来越高了,超过90%的ES6语法特性都实现了。
四、babel
被称为下一代的JavaScript编译器。可以将es6的代码转换成es5的代码,从而让浏览器获得支持