概述
基本用法
function *gen(){
console.log(1);
yield; // 产出
console.log(2);
yield;
console.log(3);
}
let g = gen();
g.next();
g.next();
g.next();
yield(产出)表达式是暂停执行的标记,而 next 方法可以恢复执行
function *gen(){
yield 1;
yield 2;
}
let g = gen();
let res1 = g.next();
console.log(res1);
let res2 = g.next();
console.log(res2);
let res3 = g.next();
console.log(res3);
function *gen(){
let res1 = yield "aaa";
console.log(res1);
let res2 = yield "bbb";
console.log(res2);
}
let g = gen();
let res1 = g.next("参数-111");
console.log(res1);
let res2 = g.next("参数-222");
console.log(res1);
let res3 = g.next("参数-333");
console.log(res1);
异步流程【手动】
function ajax(url){
return new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open("get",url,true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.status >= 200 && xhr.status < 300){
resolve(JSON.parse(xhr.responseText));
}else{
reject(xhr.responseText);
}
}
})
}
function *gen(){
let res1 = yield ajax("1.json");
console.log(res1);
let res2 = yield ajax("2.json");
console.log(res2);
}
let g = gen();
g.next().value.then(data => {
g.next(data).value.then(data => {
g.next(data);
})
})
异步流程【自动】
function *gen(){
let res1 = yield ajax("1.json");
console.log(res1);
let res2 = yield ajax("2.json");
console.log(res2);
}
function AutoRun(gen) {
let g = gen();
function next(data) {
let res = g.next(data);
if (res.done) return
res.value.then(function (data) {
next(data);
});
}
next();
}
AutoRun(gen);
类的写法
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
say(){
console.log(this.name,this.age);
}
}
let obj = new Person("haonan",100);
console.log(obj);
getter、setter
class List{
constructor(ele){
this.element = ele
}
get html(){
return this.element.innerHTML;
}
set html(arr){
this.element.innerHTML = arr.map(item = > `<li>${item}</li>`).join("");
}
}
let obj = new List(document.querySelector("#list"))
obj.html = ["aaa","bbb","ccc"];
不能在进行构造函数的时候也设置了get set已有的属性,因为此处的get set只是为了得到某个属性值或者设置某个属性值做的拦截和相应逻辑处理【与Java不同】
静态属性和静态方法
class Person{
static name = "Person类";
constructor(name,age){
this.name = name;
this.age = age;
}
say(){
console.log(this.name,this.age);
}
static eat(){
console.log("eat");
}
}
console.log(Person.name);
Person.eat();
继承
ES6 规定,子类必须在 constructor()方法重调用super(),否则就会报错。同理 Java 继承
class Person{
static name = "Person类";
constructor(name,age){
this.name = name;
this.age = age;
}
say(){
console.log(this.name,this.age);
}
static eat(){
console.log("eat");
}
}
class Student extends Person{
constructor(name,age,score){
super(name,age);
this.score = score;
}
say(){
super.say();
console.log(this.score);
}
}
let student = new Student("haonan",22,100);
console.log(student);
student.say();
// 调用静态方法
Student.eat();
使用场景,通过对象的形式接收参数渲染
<body>
<div class="box1">
<h1></h1>
<ul></ul>
</div>
<div class="box2">
<h1></h1>
<img src="" alt="" style="width: 100px;">
<ul></ul>
</div>
<script>
var data1 = {
title: "体育",
list:["体育-1","体育-2","体育-3"]
}
class CreateBox{
constructor(select,data){
this.ele = document.querySelector(select);
this.title = data.title;
this.list = data.list;
}
render(){
let h1 = this.ele.querySelector("h1");
let ul = this.ele.querySelector("ul");
h1.innerHTML = this.title;
ul.innerHTML = this.list.map(item => `<li>${item}</li>`).join("");
}
}
new CreateBox(".box1",data1).render();
let data2 = {
title: "综艺",
url:"https://pic.maizuo.com/usr/movie/5011ee407fb407d47e333a3935ec33d1.jpg?x-oSs-process=image/ quality,0_70",
list: ["综艺-1","综艺-2","综艺-3"]
}
class CreateImgBox extends CreateBox{
constructor(select,data){
super(select,data);
this.imgURL = data.url;
}
render(){
super.render();
let img = this.ele.querySelector("img");
img.src = this.imgURL;
}
}
new CreateImgBox(".box2",data2).render();
</script>
</body>
ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,再通过 import 命令输入
用法
console.log(document.querySelector("div"));
function A1(){
console.log("1.js——A1");
}
function A2(){
console.log("1.js——A2");
}
function test(){
console.log("1.js——test");
}
export default {
A1,
A2,
test
}
function B1(){
console.log("2.js——B1");
}
function test(){
console.log("2.js——test");
}
export default {
B1,
test
}
// 调用1.js中的A1 和2.js中的B1
import obj1 from "./1.js"
import obj2 from "./2.js"
obj1.A1();
obj2.B1();
export default{
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="./1.js" type="module"></script> 这种方式虽然得到了私密性,但是访问不了js文件中的东西 -->
</head>
<body>
<div></div>
<script type="module">
import obj1 from "./1.js"
import obj2 from "./2.js"
import obj3 from "./3.js"
obj1.test();
obj2.test();
</script>
</body>
</html>
导入导出写法一
export default A1
import a1 from "./1.js"
导入导出写法二
export {A1,A2}
import {A1,A2} from "./1.js"
import {A1 as a1,A2 as a2} from "./1.js"
import * as obj from "./1.js"
导入导出写法三
export function A1(){
console.log("A1");
}
export function A2(){
console.log("A2");
}
import {A1,A2} from "./1.js"
import {A1 as a1,A2 as a2} from "./1.js"
import * as obj from "./1.js"
混合写法
export {A1}
export default A2
import A2,{A1} from "./1.js"
求幂运算符
Math.pow(3,2) === 3 ** 2 //9
数组的includes方法
[1, 2, NaN].includes(NaN) // true
[1, 2, NaN].indexof(NaN) // -1
Async
async function test(){
console.log("test");
// return "success-111";
return new Promise((resolve,reject) => {
resolve("data-111");
// reject("err-222");
})
}
let res = test();
res.then(res => {
console.log("success",res);
}).catch(err => {
console.log("err",err)
})
async 返回时是非 Promise 对象,则状态为 fulfiled,then指定
async 返回的是 Promise 对象,则状态由该 Promise 对象决定
Await
function ajax(){
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log("ajax-成功");
resolve("data-111");
},1000)
})
}
async function test(){
let res = await ajax();
console.log(res);
}
test()
结合手动封装的ajax
function ajax(url){
return new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open("get",url,true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.status >= 200 && xhr.status < 300){
resolve(JSON.parse(xhr.responseText));
}else{
reject(xhr.responseText);
}
}
})
}
async function test(){
let res = await ajax("1.json");
console.log(res); // data-111
let res1 = await ajax("2.json",res);
console.log(res1); // data-222
}
test()
错误处理
try{
let res1 = await ajax("http://localhost:8080...");
let res2 = await ajax("http://localhost:8080...");
}catch(err){
console.log("err",err)
}
可以接收test()方法放回置的Promise对象进行 then 和 catch来执行相应逻辑代码,也可以在test()函数内进行try catch 来捕获执行相应逻辑代码
Object.values(obj):获取对象的所有value值
let obj = {
name: "haonan",
age: 22
}
console.log(Object.values(obj)); // ['haonan',100]
Object.entries(obj):获取对象所有的属性名和属性值
let obj = {
name: "haonan",
age: 22
}
console.log(Object.entries(obj));
Object.getOwnPropertyDescriptors(obj):获取对象的所有详细信息
let obj = {
name: "haonan",
age: 22
}
console.log(Object.getOwnPropertyDescriptors(obj));
克隆对象
let obj1 = {
name: "haonan",
age: 100,
location:{
province: "河南",
city: "洛阳",
},
// 只设置city
get city(){
return this.location.city
}
set city(value){
this.location.city = value
}
get upperName(){
return this.name
}
set upperName(value){
this.name = value.substring(0,1).toUpperCase() + value.substring(1)
}
}
let obj2 = {};
// Object.aasin(obj2,obj1); 无法克隆 get set方法
Object.defineProperties(obj2,Object.getOwnPropertiyDescriptors(obj1));
assign 无法克隆到对象的get set 方法,导致克隆遗漏,Object.getOwnPropertyDescriptors(obj)则不会
padStart()、padEnd()方法可以使得字符串达到固定长度,有两个参数,字符串目标长度和填充内容
let str = "haonan";
console.log(str.padStart(10,"x")); // xxxxhaonan
console.log(str.padEnd(10,"x")); // haonanxxxx
console.log(str.padStart(5,"x")); // haonan
console.log(str.padEnd(5,"x")); // haonan
let time = [];
for(let i = 0;i<13;i++){
time.push((i+"").padStart(2,"0"));
}
函数参数的末尾加逗号
在添加新的参数、属性、元素时有用,可以直接新加一行而不必给上一行再补充一个逗号,这样使版本控制工具的修改记录更加整洁【例如Git】
function test(
a,
b,
c,
){
console.log(a,b)
}
对象的剩余参数
let obj = {
name: "haonan",
age: 22,
location: "洛阳"
}
let {name,...other} = obj
console.log(name); // haonan
console.log(other); // {age: 22,location:'洛阳'}
对象的扩展运算符:浅复制对象
let obj1 = {
name: "mahaonan",
location: "洛阳"
}
let obj2 = {
name: "haonan",
age: 22
}
// Object.assign
let obj3 = {...obj1,...obj2};
console.log(obj3);
正则表达式命名捕获组
ES9后允许使用命名捕获,在打开捕获符号后立即命名
let str = "今天是2022-10-10";
let reg = /(?<year>0-9{4})-(?<month>0-9{2})-(?<day>0-9{2})/g;
let res1 = reg.exec(str)
console.log(res1);
无论是成功还是失败,都会运行的代码,比如隐藏对话框,关闭数据库连接等
function ajax(){
return new Promise((resolve,reject) => {
resolve(111);
})
}
// showLoading
ajax().then(res => {
}).catch(err => {
}).finally(() => {
// hideloading
})
同步遍历器问题
function *fn(){
yield 111
yield 222
}
let syncI = fn();
console.log(syncI.next());
console.log(syncI.next());
console.log(syncI.next());
function *fn(){
yield new Promise(resolve => resolve("111"));
yield new Promise(resolve => resolve("222"));
}
let syncI = fn();
syncI.next().value.then(res => console.log(res));
syncI.next().value.then(res => console.log(res));
value 属性的返回值是一个 Promise 对象,用来放置异步操作,但是这样编写较为麻烦,不符合直接,语义也比较绕
异步遍历器生成函数
async function *fn(){
yield new Promise(resolve => resolve("111"));
yield new Promise(resolve => resolve("222"));
}
let gen = fn();
gen.next().then(res => {
console.log(res);
return gen.next();
}).then(res => {
console.log(res);
return gen.next();
}).then(res => {
console.log(res);
})
for await of
for...of 循环用于遍历同步的 Iterator 接口,而改循环是用于遍历异步的 Iterator 接口
asnyc function test(){
for await(let i of gen){
console.log(i);
}
}
案例
function timer(t){
return new Promise(resolve => {
setTimeout(() => {
resolve(t);
},t)
})
}
async function *gen(){
yield timer(1000);
yield timer(2000);
yield timer(3000);
}
async function test(){
for await(let i of gen()){
console.log(i)
}
}
test()