迭代器Iterator
一种新的遍历机制,两个核心
1.迭代器是一个接口,能快捷的访问数据,通过 Symbol.iterator来创建迭代器,通过next()获取迭代之后的结果。
2.迭代器是用于遍历数据结构的指针(数据库的游标)
<script type="text/javascript">
//使用迭代
const items = ['one','two',"three"];
//创建新的迭代器
const ite = items[Symbol.iterator]()
console.log(ite.next());//{value: "one", done: false},done表示是否遍历完成,false表示遍历继续
console.log(ite.next());//{value:"two",done:false}
console.log(ite.next());//{value:"three",done:false}
console.log(ite.next());//{value:undefined,done:true}
</script>
生成器Generator
Generator函数,可以通过 yield 关键字,将函数挂起(让函数停留在当前位置),为改变执行流提供了可能性,同时为异步编程也提供了方案。
与普通函数的区别
- function 后面,函数名之前有个
* - 只能在函数内部使用
yield表达式,让函数挂起
不理解的话,参考www.w3cschool.cn/escript6/es…
<script type="text/javascript">
function* fn(){
yield 2;
yield 3;
yield 4;
}
let a =fn();//返回一个遍历器对象,可以调用next()
//理解:当函数调用时,返回了一个遍历器对象,函数并不执行
console.log(a.next());//{value:2,done:false}
console.log(a.next());//{value:3,done:false}
console.log(a.next());//{value:4,done:false}
console.log(a.next());//{value:undefined,done:true}
//总结
//generator函数是分段执行的,yield语句暂停执行,而next()恢复执行
</script>
next方法的参数
yield表达式本身没有返回值,或者说总是返回 undefined 。 next 方法可以带一个参数,该参数就会被当作上一个 yield 表达式的返回值。
function* add(){
console.log('start');
let x = yield "2";
console.log('one:'+x);
let y = yield '3';
console.log('two:'+y);
return x+y;
}
let f = add();
console.log(f.next());//start {value: "2", done: false}
console.log(f.next(10));//one:10 {value: "3", done: false}
console.log(f.next(20));//two:20 {value: 30, done: true}
console.log(f.next());// {value: undefined, done: true}
使用场景
为不具备 Iterator接口的对象提供了遍历操作
<script type="text/javascript">
//自定义生成器
function* objectEntries(obj){
// 获取对象所有的key保存到数组中[name,age]
const propsKeys = Object.keys(obj);
for (const propKey of propsKeys){
yield [propKey,obj[propKey]];
}
}
const obj = {
name:'john',
age:18
}
//构造一个生成器
obj[Symbol.iterator] = objectEntries;
console.log(obj);
for (let [key,val] of objectEntries(obj)){
//for of中做的操作逐次调用next(),返回next().value,拿到value值
console.log(`${key}:${val}`);
}
</script>
应用
可以使异步代码同步化
<!DOCTYPE html>
<html lang="zh">
<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 src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//Ajax自己去学
//作用:可以部署ajax操作,让异步代码同步化
//回调地狱
/* $.ajax({
url:'https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814',
method:'get',
success(res){
console.log(res);
//继续发送ajax
$.ajax({
url:'',
method:'get',
success(res1){
//发送请求
$.ajax({
url:'',
method:'get',
success(res2){
}
})
}
})
}
}) */
//用生成器
/* function* main(){
let res = yield request('https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814');
console.log(res);
console.log('数据请求完成');
}
const ite = main();
ite.next();
function request(url){
$.ajax({
url,
method:'get',
success(result){
//此处的next()为第二次调用
ite.next(result);
}
})
} */
/* function loadUi(){
console.log('loading');
}
function showData(){
setTimeout(()=>{
console.log('数据加载完成');
},5000)
}
function closeUi(){
console.log('关闭');
}
loadUi();
showData();
closeUi(); */
function* load(){
loadUi();
yield showData();
closeUi();
}
let itLoad = load();
itLoad.next();
function loadUi(){
console.log('loading');
}
function showData(){
//模拟异步操作
setTimeout(()=>{
console.log('数据加载完成');
itLoad.next()
},5000)
}
function closeUi(){
console.log('关闭');
}
</script>
</body>
</html>
Promise
相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果。
各种异步操作都可以用同样的方法进行处理。
特点
对象的状态不受外界影响,处理异步操作三个状态
- pending进行中
- resolved已完成
- rejected失败
一旦状态改变,就不会在变,任何时候都可以得到这个结果。
<script type="text/javascript">
/* let pro = new Promise((resolved,rejected)=>{
//执行异步操作
let res = {
code:201,
data:{
name:'john'
},
error:'failed'
};
setTimeout(()=>{
if(res.code===200){
resolved(res.data);
}else{
rejected(res.error)
}
},1000)
});
console.log(pro);//Promise object
pro.then(val=>{
console.log(val);
//val 就是res.data
},(error)=>{
console.log(error);
//error 就是res.error
}) */
//传参
function timeOut(ms){
//闭包
return new Promise((resolved,rejected)=>{
setTimeout(()=>{
resolved('hello')
},ms)
})
}
timeOut(2000).then((val)=>{
console.log(val);
});
</script>
封装Ajax
<!DOCTYPE html>
<html lang="zh">
<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 type="text/javascript">
//https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814
function getJson(url){
return new Promise((resolved,rejected)=>{
//发送ajax请求
const xhr = new XMLHttpRequest();
//方式必须大写
xhr.open('GET',url);
xhr.onreadystatechange = handler;
//返回类型
xhr.responseType = 'json';
//设置请求头
xhr.setRequestHeader('Accept','application/json');
//发送,get方法没有请求体
xhr.send();
function handler(){
// console.log(this.readyState);
if (this.readyState === 4){
if(this.status === 200){
//成功
resolved(this.response.HeWeather6)
}else{
//失败
rejected(new Error(this.statusText));
}
}
}
})
}
getJson('https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814').then((data)=>{
console.log(data);
},(error)=>{
console.log(error);
})
</script>
</body>
</html>
相关方法
then() & catch()
第一个参数是resolve回调函数,第二个参数是可选的,是reject状态回调的函数。then()返回的是一个新的promise实例,可以采用链式编程。
getJson('https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814').then((data)=>{
console.log(data);
}).then(null,err=>{
console.log(err);
})
//这样书写并不友好
//可以有替代写法,用catch
getJson('https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814').then((data)=>{
console.log(data);
}).catch(err=>{
console.log(err);
})
resolve()
能将现有的任何对象转换成promise对象
let p = Promise.resolve('foo');
// 等价于
let p = new Promise(resolve=>resolve('foo'))
console.log(p);
p.then((data)=>{
console.log(data);
})
reject()
与resolve()方法一样
all()
异步并行
let p1 =new Promise((resolve,reject)=>{})
let p2 =new Promise((resolve,reject)=>{})
let p3 =new Promise((resolve,reject)=>{})
let p4 = Promise.all([p1,p2,p3]);
p4.then(()=>{
//同则生
}).catch(err=>{
//异则死
})
race()
给某个异步的请求设置超时的时间,并且在超时后执行相应的操作
<script type="text/javascript">
//请求图片资源
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('图片请求超时'))
},2000)
})
}
Promise.race([requestImg('1.jpg'),timeOut()]).then(data=>{
console.log(data);
document.body.appendChild(data);
}).catch(err=>{
console.log(err);
})
</script>
async
返回一个promise对象,其实是generator的语法糖
作用:使异步操作更加方便
<script type="text/javascript">
async function f(){
return await 'hello'
}
//如果async函数中有多个await,那么then()会等待所有的await指令 运行完的结果才去执行
f().then(val=>{
console.log(val);
}).catch(e=>{
console.log(e);
});
async function fn(){
throw new Error('出错了')
}
fn().then(v=>{
console.log(v);
}).catch(e=>{
console.log(e);
})
</script>
封装ajax
<!DOCTYPE html>
<html lang="zh">
<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 type="text/javascript">
//https://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814
function getJson(url){
return new Promise((resolved,rejected)=>{
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.readyState);
if (this.readyState === 4){
if(this.status === 200){
resolved(this.response)
}else{
rejected(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://free-api.heweather.net/s6/weather/now?location=changchun&key=20abbcefae5c4148b23c674102d0e814')
.then(data=>{
console.log(data);
}).catch(e=>{
console.log(e)
})
</script>
</body>
</html>
class类的用法
类的创建
<script type="text/javascript">
//es5创建类
/* function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
return this.name;
}
let p = new Person('huahua','18');
console.log(p);
*/
//es6
class Person{
//实例化时,立即被调用
constructor(name,age) {
this.name = name;
this.age = age
}
/*
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
*/
}
//通过Object.assign()可以添加多个方法
Object.assign(Person.prototype,{
sayName(){
return this.name;
},
sayAge(){
return this.age;
}
})
let p = new Person('huahua',18);
console.log(p);
</script>
类的继承
<!DOCTYPE html>
<html lang="zh">
<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 type="text/javascript">
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);
//等价于
// Animal.call(this,name,age);
//子类属性
this.color = color;
}
//子类方法
sayColor(){
return `${this.name}:${this.color}`
}
//重写父类方法
sayName(){
//super相当于Animal.prototype
return this.name+ super.sayAge()+ this.color;
}
}
let d = new Dog('huahua',3,'red');
console.log(d);
console.log(d.sayName());
console.log(d.sayAge());
console.log(d.sayColor());
console.log(d.sayName());
</script>
</body>
</html>
ES6模块化的实现
es6模块功能主要有两个命令构成:export和import
一个模块就是一个独立的文件
export
用于规定模块的对外接口
index.js文件如下
export const name = 'john';
export const age = 18;
export function sayName(){
return name
}
//抛出默认值
const obj = {
foo:'foo'
}
export default obj
import
用于输入其他模块提供的功能
main.js
<script type='module'>
//此处的obj可以自定义
import obj,{name,age,sayName} from 'index.js';
/*导入所有
import * as f from 'index.js';*/
console.log(obj);
console.log(name,age,sayName());
console.log(f);
console.log(f.default);
</script>