- A+
1. ES6
1.1 let变量声明以及声明特性
声明变量
let a; let b, c, e; let f = 100, g = "红石榴21", h = [];
特性:
- 变量不能重复声明
let start = "许巍"; let start = "刀郎"; // 报错
- 块级作用域 全局、函数、eval
{ let str = "红石榴21" } console.log(str); // str is not defined
- 不存在变量提升
console.log(song); let song = "罗刹海市"; // Cannot access 'song' before initialization
- 不影响作用域链
{ let school = "国防科技大学"; function fn() { console.log(school); // 国防科技大学 } fn(); }
案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>let经典案例实践</title> <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> </head> <body> <div class="container"> <h2 class="page-header">点击切换颜色</h2> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> </div> <style> .item { width: 100px; height: 50px; border: solid 1px rgb(42, 156, 156); float: left; margin-right: 10px; } </style> <script> let items = document.getElementsByClassName("item"); // for (var i = 0; i < items.length; i++) { // items[i].onclick = function () { // this.style.background = "pink"; // for循环中,不使用let声明 // }; // } for (let i = 0; i < items.length; i++) { items[i].onclick = function () { items[i].style.background = "pink"; // for循环中,使用let声明 }; } </script> </body> </html>
1.2 const声明常量以及特点
const SCHOOL = "西南石油大学";
- 一定要赋初始值
const A; // 报错
- 一般变量使用大写(潜规则)
const A = 100;
- 常量的值不能被修改
SCHOOL = "国防科技大学"; console.log(SCHOOL); // Assignment to constant variable.
- 块级作用域
{ const YWZQ = "go"; } console.log(YWZQ); // YWZQ is not defined
- 对于数组和对象元素的修改,不算对常量的修改,不会报错
const LIKE = ["HG", "MC", "LZZ"]; LIKE.push("ZZC"); console.log(LIKE); // ['HG', 'MC', 'LZZ', 'ZZC']
1.3 变量的解构赋值
- 数组结构赋值
const F4 = ["小沈阳", "赵四", "刘能", "宋小宝"]; let [xiao, zhao, liu, song] = F4; console.log(xiao); // 小沈阳 console.log(zhao); // 赵四 console.log(liu); // 刘能 console.log(song); // 宋小宝
- 对象结构赋值
const zhao = { name: "赵本山", age: "65", xiaoping: function () { console.log("我会演小品"); }, }; let { name, age, xiaoping } = zhao; console.log(name); // 赵本山 console.log(age); // 65 console.log(xiaoping); // 输出ƒ(){} xiaoping(); // 我会演小品
console.log(zhao.name); console.log(zhao.age); zhao.xiaoping(); zhao.xiaoping();
1.4 模板字符串
- 声明变量
let str = `今天天气有点热啊`; console.log(str);
- 内容可以直接出现换行符
let str = "<ul>" + "<li>张三</li>" + "<li>李四</li>" + "<li>王五</li>" + "</ul>"; // 之前的写法 let str = `<ul> <li>张三1</li> <li>李四2</li> <li>王五3</li> </ul>`; document.getElementById("appID").innerHTML = str;
- 字符串的拼接
let str = "许巍"; let lovest = `我喜欢${str}的歌,名字叫做<<蓝莲花>>。`; console.log(lovest);
let name = "红石榴21"; let change = function () { console.log("我想改变世界!!"); }; const dream = { name, change, // improve: function () { // console.log("我又get到了新的技能!"); // }, // 简写形式 improve() { console.log("hahaha"); }, }; dream.change(); dream.improve();
1.6 箭头函数以及声明特点
let fn = function() {} let fn = function (a, b) { return a + b; }; // 调用函数 let result = fn(1, 2); console.log(result); // 3
特性:
- this 是静态的,this 始终指向函数声明时所在作用域下的 this 的值
function getName() { console.log(this.name); } let getName2 = () => { console.log(this.name); }; // 设置 window 对象的name 属性 window.name = "红石榴21"; const school = { name: "博商学院", }; // 直接调用 getName(); // 红石榴21 getName2(); // 红石榴21 // call 方法调用 getName.call(school); // 博商学院 getName2.call(school); // 红石榴21
- 不能作为构造函数实例化对象
let Person = (name, age) => { this.name = name; this.age = age; }; let me = new Person("hong", 18); console.log(me); // Person is not a constructor
- 不能使用 arguments 变量
let fn = () => { console.log(arguments); }; fn(1, 2, 3); // arguments is not defined
- 箭头函数的简写
// 1) 省略小括号,当形参有且只有一个的时候 let add = n => { return n + n; }; console.log(add(9)); // 18 // 2) 省略花括号,当代码体只有一条语句的时候,此时 return 必须省略 // 而且语句的执行结果就是函数的返回值 let pow = (n) => n * n; console.log(pow(9)); // 81
箭头函数的实践与应用场景
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>箭头函数的实践与应用场景</title> </head> <body> <div id="add"></div> <style> #add { width: 200px; height: 200px; background: #58a; } </style> <script> // 需求-1 点击 div 2s 后颜色变成『粉色』 // 获取元素 let add = document.getElementById("add"); //绑定事件 add.addEventListener("click", function () { // 1、setTimeout未使用箭头函数 //保存 this 的值 // let _this = this; // let that = this; // let self = this; // setTimeout(function () { // _this.style.background = "pink"; // }, 2000); // 2、setTimeout使用箭头函数, this 是静态的 setTimeout(() => { this.style.background = "pink"; }, 2000); }); // 需求-2 从数组中返回偶数的元素 const arr = [1, 2, 4, 6, 10, 13]; // const result = arr.filter(function (item) { // if (item % 2 === 0) { // return true; // } else { // return false; // } // }); // const result = arr.filter((item) => { // if (item % 2 === 0) { // return true; // } else { // return false; // } // }); // 简写形式 const result = arr.filter((item) => item % 2 === 0); console.log(result); // 箭头函数适合与 this 无关的回调,定时器,数组的方法回调 // 箭头函数不适合与 this 有关的回调,事件回调,对象的方法 </script> </body> </html>
- 形参初始值 具有默认值的参数,一般位置要靠后(潜规则)
function add(a, b, c) { return a + b + c; } let result = add(1, 2, 3); console.log(result); // 6 // 设置默认值 function add(a, b, c = 4) { return a + b + c; } let result = add(1, 2); console.log(result); // 7
- 与结构赋值结合
function connect({ host, username, password, port }) { console.log(host); console.log(username); console.log(password); console.log(port); } connect({ host: "127.0.0.1", username: "admin", password: "admin", port: 80, });
function date() { console.log(arguments); } date("俞老师", "王老师", "顾老师");
rest 参数
function date(...args) { console.log(args); // [俞老师", "王老师", "顾老师] 变成数组就可以使用 filter、some、every、map } date("俞老师", "王老师", "顾老师");
function fn(a, b, ...args) { console.log(a); // 1 console.log(b); // 2 console.log(args); // [3, 4, 5, 6] } fn(1, 2, 3, 4, 5, 6);
1.9 扩展运算符的介绍
// 声明一个数组 const tfbody = ["朴树", "许巍", "刀郎"]; // 声明一个函数 function likeSinger() { console.log(arguments); } likeSinger(...tfbody); console.log(tfbody);
输出结果
扩展运算符的应用
- 数组的合并
const siDaTianWang = ["刘德华", "张学友", "郭富城", "黎明"]; const xiaoHuDui = ["吴奇隆", "陈志朋", "苏有朋"]; // const zuHe = siDaTianWang.concat(xiaoHuDui); // 使用concat实现数组拼接 // console.log(zuHe); // ["刘德华", "张学友", "郭富城", "黎明","吴奇隆", "陈志朋", "苏有朋"] const zuHe = [...siDaTianWang, ...xiaoHuDui]; console.log(zuHe); // ["刘德华", "张学友", "郭富城", "黎明","吴奇隆", "陈志朋", "苏有朋"]
- 数组的克隆
const ziMu = ["A", "B", "C"]; const newArr = [...ziMu]; console.log(ziMu); // ["A", "B", "C"] console.log(newArr); // ["A", "B", "C"]
- 将伪数组转为真正的数组
const divS = document.querySelectorAll("div"); const divArr = [...divS]; console.log(divArr);
输出结果
- 创建Symbol
let s = Symbol(); console.log(s, typeof s); // Symbol() 'symbol' let s2 = Symbol("嘀嘀咕咕"); let s3 = Symbol("嘀嘀咕咕"); console.log(s2, typeof s2); // Symbol(嘀嘀咕咕) 'symbol' console.log(s2 === s3); // false
- Symbol.for 创建
let s4 = Symbol.for("我的心思"); let s5 = Symbol.for("我的心思"); console.log(s4); // Symbol(我的心思) console.log(s4 === s5); // true
- 不能与其他数据进行运算
let result = s + 100; // Cannot convert a Symbol value to a number let result = s > 100; // Cannot convert a Symbol value to a number let result = s + s; // Cannot convert a Symbol value to a number // USONB you are so niubility // u undefined // s string symbol // o object // n null number // b boolean
1.10.2 对象添加Symbol类型的属性
let game = { name: "学爸", up: function () {}, down: function () {}, }; // 声明一个对象 let methods = { up: Symbol(), down: Symbol(), }; // console.log(methods); game[methods.up] = function () { console.log("我可以改变世界!"); }; game[methods.down] = function () { console.log("海鲜都留给小日子吃吧!"); }; console.log(game);
输出结果
let phws = { name: "排核污水", [Symbol("say")]: function () { console.log("打断小日子的狗腿"); }, [Symbol("woof")]: function () { console.log("小日子公开食海鲜,真香"); }, }; console.log(phws);
输出结果
1.10.3 Symbol的内置属性
- Symbol.hasInstance
class Person { static [Symbol.hasInstance](param) { console.log(param); console.log("我被用来检测类型了"); return true; } } let o = {}; console.log(o instanceof Person);
- Symbol.isConcatSpreadable
const arr = [1, 2, 3]; const arr2 = [4, 5, 6]; arr2[Symbol.isConcatSpreadable] = false; console.log(arr.concat(arr2));
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11个内置的 Symbol值,指向语言内部使用的方法。
1.11.1 迭代器介绍
- ES6 创造了一种新的遍历命令 for...of 循环,lterator 接口主要供 for...of 消费
- 原生具备 iterator 接口的数据(可用 for of 遍历)
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
- 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和done 属性的对象
注:需要自定义遍历数据的时候,要想到迭代器。
// 声明一个数组 const tangShengShiTu = ["唐僧", "孙悟空", "猪八戒", "沙和尚"]; // 使用 for...of 遍历数组 // for (let v of tangShengShiTu) { // console.log(v); // "唐僧", "孙悟空", "猪八戒", "沙和尚" // } let iterator = tangShengShiTu[Symbol.iterator](); // 调用对象的next方法 console.log(iterator.next()); // {value: '唐僧', done: false} console.log(iterator.next()); // {value: '孙悟空', done: false} console.log(iterator.next()); // {value: '猪八戒', done: false} console.log(iterator.next()); // {value: '沙和尚', done: false} console.log(iterator.next()); // {value: '', done: true}
1.11.2 迭代器应用-自定义遍历数据
// 声明一个对象 const banJi = { name: "朗月班", stuList: ["xiaohong", "xiaolian", "xiaojia", "xiaoyuan"], [Symbol.iterator]() { // 索引变量 let index = 0; // let _this = this; // return { // next: function () { // if (index < _this.stuList.length) { // const result = { value: _this.stuList[index], done: false }; // // 下标自增 // index++; // // 返回结果 // return result; // } else { // return { value: _this.stuList[index], done: true }; // } // }, // }; // 使用箭头函数 let next = () => { if (index < this.stuList.length) { const result = { value: this.stuList[index], done: false }; // 下标自增 index++; // 返回结果 return result; } else { return { value: this.stuList[index], done: true }; } }; return { next }; }, }; // 需求: 只能使用for of 遍历stuList,通过面向对象 // 不能使用 banJi.stuList.forEach for (let v of banJi) { console.log(v); // "xiaohong", "xiaolian", "xiaojia", "xiaoyuan" }
1.12.1 生成器函数声明与调用
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
// 生成器其实就是一个特殊的函数 // 异步编程 纯回调函数 node fs ajax mongodb // 函数代码的分隔符 function* gen() { console.log("hello generator"); // hello generator } let iterator = gen(); iterator.next();
另一个例子
function* gen() { console.log(111); yield "光辉岁月"; console.log(222); yield "蓝莲花"; console.log(333); yield "像风一样自由"; console.log(444); } let iterator = gen(); console.log(iterator.next()); // 111 {value: '光辉岁月', done: false} console.log(iterator.next()); // 222 {value: '蓝莲花', done: false} console.log(iterator.next()); // 333 {value: '像风一样自由', done: false} console.log(iterator.next()); // 444 {value: 'undefined', done: true} // 遍历 for (let v of gen()) { console.log(v); }
遍历输出结果
1.12.2 生成器函数的参数传递
function* gen() { yield 111; yield 222; yield 333; } // 执行获取迭代器对象 let iterator = gen(); console.log(iterator.next()); // {value: 111, done: false} console.log(iterator.next()); // {value: 222, done: false} console.log(iterator.next()); // {value: 333, done: false} console.log(iterator.next()); // {value: undefined, done: true}
另一个例子
function* gen(arg) { console.log(arg); let one = yield 111; console.log(one); let two = yield 222; console.log(two); let three = yield 333; console.log(three); } // 执行获取迭代器对象 let iterator = gen("AAA"); console.log(iterator.next()); // next方法可以传入实参 console.log(iterator.next("BBB")); // 第二次调用作为第一个yield的返回参数 console.log(iterator.next("CCC")); // 第三次调用作为第二个yield的返回参数 console.log(iterator.next("DDD")); // 第四次调用作为第三个yield的返回参数 console.log(iterator.next("FFF"));
输出结果
1.12.3 生成器函数实例
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); }, 3000); } function* gen() { yield one(); yield two(); yield three(); } // 调用生成器函数 let iterator = gen(); iterator.next();
输出结果
1.12.4 生成器函数实例-2
function getUsers() { setTimeout(() => { let data = "用户数据"; console.log(data); iterator.next(); }, 1000); } function getOrders() { setTimeout(() => { let data = "订单数据"; console.log(data); iterator.next(); }, 1000); } function getGoods() { setTimeout(() => { let data = "商品数据"; console.log(data); }, 1000); } function* gen() { yield getUsers(); yield getOrders(); yield getGoods(); } // 调用生成器函数 let iterator = gen(); iterator.next();
输出结果
需求-2,补充调用传参
function getUsers() { setTimeout(() => { let data = "用户数据1"; iterator.next(data); }, 1000); } function getOrders() { setTimeout(() => { let data = "订单数据2"; iterator.next(data); }, 1000); } function getGoods() { setTimeout(() => { let data = "商品数据3"; iterator.next(data); }, 1000); } function* gen() { let users = yield getUsers(); console.log(users); let orders = yield getOrders(); console.log(orders); let goods = yield getGoods(); console.log(goods); } // 调用生成器函数 let iterator = gen(); iterator.next();
输出结果
1.13.1 Promise介绍与基本使用
Promise 是ES6引入的异步编程的新解决方案。语法上 Promise 是一个构造函数用来封装异步操作并可以获取其成功或失败的结果。
- Promise构造函数:Promise(excutor)
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
// 实例化 Promise 对象 const p = new Promise(function (resolve, reject) { setTimeout(() => { // let data = "读取用户数据"; // resolve(data); let err = "读取数据失败!"; reject(err); }, 1000); }); // 调用 promise 对象的 then 方法 p.then( function (value) { console.log(value); // 读取用户数据 }, function (error) { console.error(error); // 读取数据失败! } );
1.13.2 Promise封装读取文件
// 1、引入 fs 模块 const fs = require("fs"); // 2、调用方法读取文件 // fs.readFile('./resources/为学.md', (err, data) => { // // 如果失败,则抛出错误 // if (err) throw err; // // 如果没有出错,则输出内容 // console.log(data.toString()); // }); // 3、使用 Promise 封装 const p = new Promise(function (resolve, reject) { fs.readFile("./resources/为学.md", (err, data) => { // 判断如果失败 if (err) reject(err); // 如果成功 resolve(data); }); }); p.then(function (value) { console.log(value.toString()); }, function (err) { console.log("读取失败!!") })
输出结果
1.13.3 Promise封装AJAX请求
- 方法-1 普通写法
// 接口地址: https://api.apiopen.top/api/getDynamic // 1、创建对象 const xhr = new XMLHttpRequest(); // 2、初始化 xhr.open("GET", "https://api.apiopen.top/api/getDynamic"); // 3、发送 xhr.send(); // 4、绑定事件,处理响应结果 xhr.onreadystatechange = function () { // 判断 if (xhr.readyState === 4) { // 判断响应状态码 200-299 if (xhr.status >= 200 && xhr.status < 300) { console.log(xhr.response); } else { // 如果失败 console.log(xhr.status); } } };
- 方法-2 Promise封装
const p = new Promise((resolve, reject) => { // 1、创建对象 const xhr = new XMLHttpRequest(); // 2、初始化 xhr.open("GET", "https://api.apiopen.top/api/getDynamic"); // 3、发送 xhr.send(); // 4、绑定事件,处理响应结果 xhr.onreadystatechange = function () { // 判断 if (xhr.readyState === 4) { // 判断响应状态码 200-299 if (xhr.status >= 200 && xhr.status < 300) { // 表示成功 resolve(xhr.response); } else { // 如果失败 reject(xhr.status); } } }; }); // 指定回调 p.then( function (value) { console.log(value); }, function (error) { console.log(error); } );
1.13.4 Promise.prototype..then方法
// 创建 promise 对象 const p = new Promise((resolve, reject) => { setTimeout(() => { resolve("获取用户数据成功!"); }, 1000); }); // 调用 then 方法 then方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定 // 1、如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功,返回值为对象的成功的值 const result = p.then( (value) => { // console.log(value); // 1、非 promise 类型的属性 return "I Love You"; // 2、是promise 对象 // return new Promise((resolve, reject) => { // resolve("ok"); // reject('error'); // }); // 3、抛出错误 // throw new Error("出错啦!"); // throw '出错啦!' }, (reason) => { console.error(reason); } ); console.log(result); // p.then( // (value) => { // console.log(value); // }, // (error) => { // console.log(error); // } // ); // 链式调用 p.then(value=>{ }).then(reason=>{ })
1.13.5 Promise实践练习-多个文件内容读取
- 方法-1 回调地狱
fs.readFile("./resources/为学.md", (err, data1) => { fs.readFile("./resources/插秧诗.md", (err, data2) => { fs.readFile("./resources/观书有感.md", (err, data3) => { // let result = data1 + 'rn' + data2 + 'rn' + data3; let result = `${data1}rn${data2}rn${data3}` console.log(result); }) }) });
- 方法-2 使用 promise 实现
const p = new Promise((resolve, reject) => { fs.readFile("./resources/为学.md", (err, data) => { resolve(data); }) }); p.then(value => { return new Promise((resolve, reject) => { fs.readFile("./resources/插秧诗.md", (err, data) => { resolve([value, data]); }) }) }).then(value => { return new Promise((resolve, reject) => { fs.readFile("./resources/观书有感.md", (err, data) => { // 压入 value.push(data); resolve(value); }); }) }).then(value => { console.log(value.join('rn')); })
- 方法-3 使用生成器函数
function one() { fs.readFile("./resources/为学.md", (err, data) => { iterator.next(data); }) } function two() { fs.readFile("./resources/插秧诗.md", (err, data) => { iterator.next(data); }) } function three() { fs.readFile("./resources/观书有感.md", (err, data) => { iterator.next(data); }) } function* gen() { let a = yield one(); let b = yield two(); let c = yield three(); let d = `${a}rn${b}rn${c}`; console.log(d.toString()); }; // 调用生成器函数 let iterator = gen(); iterator.next();
输出结果
1.13.6 Promise对象catch方法
const p = new Promise((resolve, reject) => { setTimeout(() => { // 设置 P 对象的状态为失败,并设置失败的值 reject("出错啦!"); }, 1000); }); // p.then(value=> { // console.log(value); // }, reason=>{ // console.log(reason); // }); p.catch((reason) => { console.warn(reason); // 出错啦! });
1.14 ES6-集合介绍与API
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的集合实现了 iterator 接口,所以可以使用[扩展运算符]和[for...of...] 进行遍历集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete 删除元素,返回 boolean 值
- has 检测集合中是否包含某个元素,返回 boolean 值
// 声明一个 set let s = new Set(); console.log(s); // Set(0) {size: 0} let s2 = new Set(["昨天", "今天", "明天", "未来", "今天"]); console.log(s2); // Set(4) {'昨天', '今天', '明天', '未来'} // 元素的个数 console.log(s2.size); // 添加新的元素 s2.add("过去"); console.log(s2); // Set(5) {'昨天', '今天', '明天', '未来', '过去'} // 删除元素 s2.delete("昨天"); console.log(s2); // Set(4) {'今天', '明天', '未来', '过去'} // 清空 s2.clear(); console.log(s2); // Set(0) {size: 0}
1.15 ES6-集合实践
- 数组去重
let result = [...new Set(arr)]; console.log(result); // [1, 2, 3, 4, 5]
- 交集
let arr2 = [4, 5, 6, 5, 6]; let result = [...new Set(arr)].filter((item) => { let s2 = new Set(arr2); // 去重后,4 5 6 if (s2.has(item)) { return true; } else { return false; } }); console.log(result); // [4, 5]
交集的简写形式
let arr2 = [4, 5, 6, 5, 6]; let result = [...new Set(arr)].filter(item=>new Set(arr2).has(item)); console.log(result); // [4, 5]
- 并集
let arr2 = [4, 5, 6, 5, 6]; let union = [...new Set([...arr, ...arr2])]; console.log(union); // [1, 2, 3, 4, 5, 6]
- 差集
let arr2 = [4, 5, 6, 5, 6]; let diff = [...new Set(arr)].filter(item=>!(new Set(arr2).has(item))); console.log(diff); // [1, 2, 3]
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用[扩展运算符]和[for...of...] 进行遍历。Map的属性和方法:
- size 返回Map的元素个数
- set 增加一个新元素,返回当前 Map
- get 返回键名对象的键值
- has 检测 Map 中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回undefined
// 声明 Map let m = new Map(); // console.log(m); // 添加元素 m.set("name", "成都大运会"); // console.log(m); // Map(1) {'name' => '成都大运会'} m.set("change", function () { console.log("我可以改变世界!!"); }); let key = { school: "西南石油大学", }; m.set(key, ["北京", "上海", "广州", "深圳"]); // console.log(m); // size // console.log(m.size); // 3 // 删除 // m.delete("name"); // console.log(m); // 清空 // m.clear(); // console.log(m); // Map(0) {size: 0} // 遍历 for(let v of m) { console.log(v); }
1.17.1 ES6-class介绍与初体验
ES6 提供了更接近传统语言的写法,引入了 class(类) 这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。知识点:
- class声明类
- constructor 定义构造函数初始化
- extends 继承父类
- super 调用父级构造方法
- static 定义静态方法和属性
- 父类方法可以重写
// ES5 function Huawei(bank, price) { this.bank = bank; this.price = price; } // 在原型上添加方法 Huawei.prototype.call = function () { console.log("我可以打电话哦!"); }; let hW = new Huawei("3999", "华为荣耀"); hW.call(); console.log(hW); // ES6 class XiaoMi { constructor(bank, price) { this.bank = bank; this.price = price; } // 方法必须使用该语法,不能使用 ES5 的对象完整形式 call() { console.log("我为发烧而生"); } } let xM = new XiaoMi("699", "红米"); xM.call(); console.log(xM);
输出结果
1.17.2 ES6-class静态成员
// 构造函数也是一个对象 function Phone() {} Phone.name = "手机"; Phone.change = function () { console.log("我可以改变世界!"); }; Phone.prototype.size = "5.5inch"; // 实例对象是实例对象,函数对象是函数对象。 let tianYu = new Phone(); console.log(tianYu.name); // undefined // tianYu.change(); // error tianYu.change is not a function console.log(tianYu.size); // 5.5inch class Computer { // 静态属性 static name = "戴尔"; static change() { console.log("我可以改变世界!"); } } let dianNao = new Computer(); console.log(dianNao.name); // undefined // 静态方法是属于类,不属于实例方法 console.log(Computer.name); // 戴尔
// 手机 function Phone(brand, price) { this.brand = brand; this.price = price; } Phone.prototype.call = function () { console.log("我可以打电话"); }; // 智能手机 function SmartPhone(brand, price, color, size) { Phone.call(this, brand, price); this.color = color; this.price = price; } // 设置子构造函数的原型 SmartPhone.prototype = new Phone(); // 校正一下,你不这样做也行 // SmartPhone.prototype.constructor = SmartPhone; // 声明子类的方法 SmartPhone.prototype.photo = function () { console.log("我可以拍照"); }; SmartPhone.prototype.playGame = function () { console.log("我可以打游戏"); }; const chuiZi = new SmartPhone("锤子", 2999, "黑色", "5.5inch"); console.log(chuiZi); chuiZi.call(); chuiZi.photo(); chuiZi.playGame();
输出结果
1.17.4 ES6-class的类继承
class Phone { // 构造方法 constructor(brand, price) { this.brand = brand; this.price = price; } call() { console.log("我可以打电话!"); } } class SmartPhone extends Phone { // 构造方法 constructor(brand, price, color, size) { super(brand, price); // Phone.call(this, brand, price); this.color = color; this.size = size; } photo() { console.log("我能拍照!"); } playGame() { console.log("我能玩游戏!"); } } let xiaoMi = new SmartPhone("小米", 699, "黑色", "5.5inch"); console.log(xiaoMi); xiaoMi.call(); xiaoMi.photo(); xiaoMi.playGame();
输出结果
1.17.4 ES6-子类对父类方法的重写
class Phone { // 构造方法 constructor(brand, price) { this.brand = brand; this.price = price; } call() { console.log("我可以打电话!"); } } class SmartPhone extends Phone { // 构造方法 constructor(brand, price, color, size) { super(brand, price); // Phone.call(this, brand, price); this.color = color; this.size = size; } photo() { console.log("我能拍照!"); } playGame() { console.log("我能玩游戏!"); } // ES6-子类对父类方法的重写 call() { console.log("我可以视频通话哦!"); } } let xiaoMi = new SmartPhone("小米", 699, "黑色", "5.5inch"); console.log(xiaoMi); xiaoMi.call(); xiaoMi.photo(); xiaoMi.playGame();
输出结果
1.18 ES6的数值扩展
- Number.EPSILON 是 JavaScript 表示的最小精度
function equal(a, b) { if (Math.abs(a - b) < Number.EPSILON) { return true; } else { return false; } } console.log(0.1 + 0.2); // 0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // false console.log(equal(0.1 + 0.2, 0.3)); // true
- 二进制和八进制
let b = 0b1010; console.log(b); // 10 let o = 0o777; console.log(o); // 511 let d = 100; console.log(d); // 100 let x = 0xff; console.log(x); // 255
- Number.isNaN 检测一个数值是否为 NaN
console.log(Number.isNaN(123)); // false
- Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt("511111fuck")); // 511111 console.log(Number.parseFloat("3.1415926疯狂")); // 3.1415926
- Number.isInteger() 判断一个数是否为整数
console.log(Number.isInteger(5)); // true console.log(Number.isInteger(2.5)); // false
- Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5)); // 3
- Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100)); // 1 console.log(Math.sign(0)); // 0 console.log(Math.sign(-20000)); // -1
1.19 ES6的对象方法扩展
- Object.is 判断两个值是否完全相等
console.log(Object.is(120, 120)); // true === console.log(Object.is(NaN, NaN)); // true console.log(NaN === NaN); // false
- Object.assign 对象的合并
const obj1 = { host: "localhost", port: 3306, username: "admin", password: "admin", }; const obj2 = { host: "127.0.0.1", port: 8080, username: "root", password: "root", isLogin: false, }; console.log(Object.assign(obj1, obj2)); // {host: '127.0.0.1', port: 8080, username: 'root', password: 'root', isLogin: false}
- Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = { name: "研究院", }; const cities = { xiaoqu: ["北京", "上海", "广州"], }; Object.setPrototypeOf(school, cities); console.log(Object.getPrototypeOf(school)); console.log(school);
输出结果
1.20.1 ES6-模块化介绍、优势以及产品
- 模块化
- 模块化的好处
- 模块化规范产品
- ES6 模块化语法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES6-浏览器使用ES6模块化引入模块</title> </head> <body> <script type="module"> // 引入 m1.js 模块内容 import * as m1 from "./src/js/m1.js"; console.log(m1); m1.study(); </script> </body> </html>
js代码-m1.js
// 分别暴露 export let school = "西南石油大学"; export function study() { console.log("我可以学习到新的技能!!") }
1.20.3 ES6模块暴露数据语法汇总
html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES6模块暴露数据语法汇总</title> </head> <body> <script type="module"> // 引入 m1.js 模块内容 import * as m1 from "./src/js/m1.js"; console.log(m1); m1.study(); // 引入 m2.js 模块内容 import * as m2 from "./src/js/m2.js"; console.log(m2); m2.findJob(); // 引入 m3.js 模块内容 import * as m3 from "./src/js/m3.js"; console.log(m3); m3.default.change(); </script> </body> </html>
js代码-m2.js
// 统一暴露 let school = "西南石油大学"; function findJob() { console.log("我一定能行!"); } export { school, findJob };
js代码-m3.js
// 默认暴露 export default { school: "西南石油大学", change: function () { console.log("我可以改变自己!"); } }
1.20.4 ES6引入模块数据语法汇总
html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES6引入模块数据语法汇总</title> </head> <body> <script type="module"> // 1、通用的导入方法 // 引入 m1.js 模块内容 import * as m1 from "./src/js/m1.js"; // console.log(m1); // m1.study(); // 引入 m2.js 模块内容 import * as m2 from "./src/js/m2.js"; // console.log(m2); // m2.study(); // 引入 m3.js 模块内容 // import * as m3 from "./src/js/m3.js"; // console.log(m3); // m3.default.study(); // 2、结构赋值形式 // import { school, study } from "./src/js/m1.js"; // console.log(school); // study(); // 使用别名 // import { school as xueXiao, study as learn } from "./src/js/m2.js"; // console.log(xueXiao); // learn(); // import { default as m3 } from "./src/js/m3.js"; // console.log(m3); // 3、简便形式 针对默认暴露 import m3 from "./src/js/m3.js"; console.log(m3); </script> </body> </html>
1.20.5 ES6-浏览器使用ES6模块化方式二
html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES6-浏览器使用ES6模块化方式二</title> </head> <body> <!-- 模块化方式一 --> <script type="module"> // 1、通用的导入方法 // 引入 m1.js 模块内容 // import * as m1 from "./src/js/m1.js"; // console.log(m1); // m1.study(); // 引入 m2.js 模块内容 // import * as m2 from "./src/js/m2.js"; // console.log(m2); // m2.study(); // 引入 m3.js 模块内容 // import * as m3 from "./src/js/m3.js"; // console.log(m3); // m3.default.study(); // 2、结构赋值形式 // import { school, study } from "./src/js/m1.js"; // console.log(school); // study(); // 使用别名 // import { school as xueXiao, study as learn } from "./src/js/m2.js"; // console.log(xueXiao); // learn(); // import { default as m3 } from "./src/js/m3.js"; // console.log(m3); // 3、简便形式 针对默认暴露 // import m3 from "./src/js/m3.js"; // console.log(m3); </script> <!-- 模块化方式二 --> <script src="./src/js/app.js" type="module"></script> </body> </html>
1.20.6 ES6-babel对ES6模块化代码转换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES6-babel对ES6模块化代码转换</title> </head> <body> <!-- 步骤: 0、先做一个初始化 npm init --yes 1、安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D 2、编译 npx babel src/js -d dist/js --presets=babel-preset-env 3、打包 npx browserify dist/js/app.js -o dist/bundle.js --> <script src="./dist/bundle.js" type="module"></script> </body> </html>
1.20.7 ES6模块化引入NPM包
1)安装jquery npm i jquery
2)html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES6模块化引入NPM包</title> </head> <body> <script src="./dist/bundle.js" type="module"></script> </body> </html>
3)js代码-app.js
import $ from 'jquery'; // const $ = require("jquery"); $("body").css("background", "pink");
2. ES7
2.1 ES7新特性
- Arrayprototype.includes
const mingZhu = ["西游记", "红楼梦", "三国演义", "水浒传"]; console.log(mingZhu.includes("西游记")); // true console.log(mingZhu.includes("石头记")); // false
- 指数操作符
console.log(2 ** 10); // 1024 console.log(Math.pow(2, 10)); // 1024
3. ES8
3.1 ES8-async函数
- async和await
async和await两种语法结合可以让异步代码像同步代码一样
- async函数
1)async函数的返回值为 promise 对象,
2)promise对象的结果由 async函数执行的返回值决定
// async 函数 async function fn() { // 返回一个字符串 // return "好炎热"; // 返回的结果不是一个 Promise 类型的对象,返回的结果就是成功 Promise 对象 // return; // 抛出错误,返回的结果是一个失败的 Promise // throw new Error("出错啦!"); // 返回的结果如果是一个 Promise 对象 return new Promise((resolve, reject) => { // resolve("读取数据成功!"); reject("读取数据失败!"); }); } const result = fn(); // console.log(result); // 调用 then 方法 result.then(value => { console.log(value); },reason => { console.warn(reason); } );
3.2 ES8-await表达式
- await 表达式
1)await 必须写在async函数中
2)await 右侧的表达式一般为 promise 对象
3)await 返回的是 promise 成功的值
4)await 的 promise 失败了,就会抛出异常,需要通过 try...catch 捕获处理
// 创建 Promise 对象 let p = new Promise((resolve, reject) => { // resolve("请求成功!"); reject("请求失败!"); }); // await 要放在 async 函数中. async function main() { try { let result = await p; console.log(result); } catch (e) { console.error(e); } } // 调用函数 main();
3.3 ES8-async与await结合读取文件内容
// 引入fs const fs = require("fs"); // 读取为学 function readWeiXue() { return new Promise((resolve, reject) => { fs.readFile("./resources/为学.md", (err, data) => { // 如果失败 if (err) reject(err); // 如果成功 resolve(data); }) }) } // 读取插秧诗 function readChaYangShi() { return new Promise((resolve, reject) => { fs.readFile("./resources/插秧诗.md", (err, data) => { // 如果失败 if (err) reject(err); // 如果成功 resolve(data); }) }) } // 读取观书有感 function readGuanShu() { return new Promise((resolve, reject) => { fs.readFile("./resources/观书有感.md", (err, data) => { // 如果失败 if (err) reject(err); // 如果成功 resolve(data); }) }) } //声明一个 async 函数 async function main() { // 获取为学内容 let weiXue = await readWeiXue(); // 获取插秧诗内容 let chaYang = await readChaYangShi(); // 获取观书有感 let guanShu = await readGuanShu(); console.log(weiXue.toString()); console.log(chaYang.toString()); console.log(guanShu.toString()); } main();
3.4 ES8-async与await结合发送AJAX请求
// 发送 AJAX 请求,返回的结果是 Promise 对象 function sendAJAX(url) { return new Promise((resolve, reject) => { // 1、创建对象 const x = new XMLHttpRequest(); // 2、初始化 x.open("GET", url); // 3、发送 x.send(); // 4、事件绑定 x.onreadystatechange = function () { if (x.readyState === 4) { if (x.status >= 200 && x.status < 300) { // 请求成功 resolve(x.response); } else { // 请求失败 reject(x.status); } } }; }); } // Promise then 方法的测试 // sendAJAX("https://api.apiopen.top/api/getDynamic").then(value=>{ // console.log(value); // },reason=>{ // }); // async 与 await 测试 async function main() { // 发送 AJAX 请求 let result = await sendAJAX("https://api.apiopen.top/api/getDynamic"); // console.log(result); let tianQi = await sendAJAX( "https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P" ); console.log(tianQi); } main();
3.5 ES8对象方法扩展
- Obiect.values 和 Obiect.entries
// 声明对象 const school = { name: "西南石油大学", xiaoqu: ["新都", "南充"], major: ["计算机科学与技术", "软件工程", "人工智能"], };
entries
- Object.getOwnPropertyDescriptors
使用Object.create()创建对象
const obj = Object.create(null, { name: { // 设置值 value: "哈哈", // 属性特征 writable: true, configurable: true, enumerable: true, }, }); console.log(obj); // {name: '哈哈'}
4. ES9
4.1 ES9扩展运算符与rest参数
function connect({ host, port, ...user }) { console.log(host); // 127.0.0.1 console.log(port); // 3306 console.log(user); // {username: 'root', password: 'root', type: 'master'} } connect({ host: "127.0.0.1", port: 3306, username: "root", password: "root", type: "master", });
const skillOne = { a: "html5", k: "其他", }; console.log({ ...skillOne }); // {a: 'html5', k: '其他'} // console.log({ ...skillOne }['a']); // html5 const skillTwo = { b: "css3", }; const skillThree = { c: "vue3", }; const skillFour = { d: "react", }; const skill = { ...skillOne, ...skillTwo, ...skillThree, ...skillFour }; console.log(skill); // {a: 'html5', k: '其他', b: 'css3', c: 'vue3', d: 'react'} console.log(skill["d"]); // react
4.2 ES9正则扩展-命名捕获分组
// 提取 url 与 『标签文本』 const reg = /<a href="(.*)">(.*)</a>/; // 执行 const result = reg.exec(str); console.log(result); console.log(result[1]); // https://www.baidu.com console.log(result[2]); // 百度
输出结果
分组命名
const reg = /<a href="(?<url>.*)">(?<text>.*)</a>/; const result = reg.exec(str); console.log(result); console.log(result.groups.url); // https://www.baidu.com console.log(result.groups.text); // 百度
输出结果
4.3 ES9正则扩展-反向断言
const reg = /d+(?=啦)/; const result = reg.exec(str); console.log(result);
const reg = /(?<=么)d+/; const result = reg.exec(str); console.log(result);
输出结果
4.4 ES9正则扩展-dotAll模式
let str = ` <ul> <li> <a>肖生克的救赎</a> <p>上映日期: 1994-09-10</p> </li> <li> <a>阿甘正传</a> <p>上映日期: 1994-07-06</p> </li> </ul>`; // 声明正则 // const reg = /<li>s+<a>(.*?)</a>s+<p>(.*?)</p>/; const reg = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs; // 执行匹配 let result; let data = []; while ((result = reg.exec(str))) { data.push({ title: result[1], time: result[2] }); } // 输出结果 console.log(data);
输出结果
5. ES10
5.1 ES10-对象扩展方法Object.fromEntries
// 二维数组转换成对象 const result = Object.fromEntries([ ["name", "西南石油大学"], ["zhuanYe", "计算机科学与技术, 软件工程, 人工智能"], ]); console.log(result); // {name: '西南石油大学', zhuanYe: '计算机科学与技术, 软件工程, 人工智能'} // Map const m = new Map(); m.set("name", "电子科大"); m.set("zhuanYe", "大数据"); const result = Object.fromEntries(m); console.log(result); // {name: '电子科大', zhuanYe: '大数据'} // Object.entries ES8 对象转二维数组 const arr = Object.entries({ name: "红石榴21", }); console.log(arr); // [["name","红石榴21"]]
5.2 ES10-字符串方法扩展-trimStart-trimEnd
- trim
let str = " Hello World "; console.log(str); console.log(str.trimStart()); console.log(str.trimEnd());
输出结果
5.3 ES10-数组方法扩展-flat与flatMap
- flat 平铺
const arr = [1, 2, 3, 4, [5, 6]]; console.log(arr.flat()); // [1, 2, 3, 4, 5, 6] const arr2 = [1, 2, 3, [5, 6, [7, 8, 9]]]; // 参数为深度 是一个数字 console.log(arr2.flat(2)); // [1, 2, 3, 5, 6, 7, 8, 9]
- flatMap
const arr3 = [1, 2, 3, 4]; const result = arr3.flatMap((item) => [item * 10]); console.log(result); // [10, 20, 30, 40]
5.4 ES10-Symbol.prototype.description
// 创建Symbol let s = Symbol("西南石油大学"); console.log(s.description); // 西南石油大学
6. ES11
class Person { // 公有属性 name; // 私有属性 #age; #weight; // 构造方法 constructor(name, age, weight) { this.name = name; this.#age = age; this.#weight = weight; } intro() { console.log(this.name); // 尕车 console.log(this.#age); // 18 console.log(this.#weight); // 45kg } } // 实例化 const girl = new Person("尕车", 18, "45kg"); console.log(girl.name); // console.log(girl.#age); // error // console.log(girl.#weight); // error girl.intro();
6.2 ES11-Promise.allSettled方法
// 声明两个Promise对象 const p1 = new Promise((resolve, reject) => { setTimeout(() => { // resolve("商品数量-1"); reject("出错啦!"); }, 1000); }); const p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve("商品数量-2"); }, 1000); }); // 调用allSettled 方法 // 就算有一个失败,也会都会返回 const result = Promise.allSettled([p1, p2]); console.log(result); // 调用all 方法 // 两个都成功,才会返回结果 const res = Promise.all([p1, p2]); console.log(res);
调用allSettled 方法,输出结果
6.3 ES11-String.prototype.matchAll方法
let str = `<ul> <li> <a>肖生克的救赎</a> <p>上映日期: 1994-09-10</p> </li> <li> <a>阿甘正传</a> <p>上映日期: 1994-07-06</p> </li> </ul>`; // 声明正则 const reg = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs; // 调用方法 const result = str.matchAll(reg); // for(let v of result){ // console.log(v); // } // console.log(result); const arr = [...result]; console.log(arr);
6.4 ES11-可选链操作符
function main(config) { // const dbHost = config && config.db && config.db.host; const dbHost = config?.db?.host; console.log(dbHost); } main({ db: { host: "127.0.0.1", username: "root" }, cache: { host: "127.0.0.2", username: "admin" }, });
6.5 ES11-动态import
html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES11-动态import</title> </head> <body> <button id="btn">点击</button> <script src="./js/app.js" type="module"></script> </body> </html>
app.js
// import * as m1 from "./hello.js"; 静态 import // 获取元素 const btn = document.getElementById("btn"); btn.onclick = function () { // 动态 import import('./hello.js').then(module => { module.hello(); }) }
hello.js
export function hello() { alert("Hello"); }
6.6 ES11-BigInt类型
// 大整形 // let n = 521n; // console.log(n, typeof n); // 521n 'bigint' // 函数 // let n = 123; // console.log(BigInt(n)); // 123n // console.log(BigInt(1.2)); // error // 大数值运算 let max = Number.MAX_SAFE_INTEGER; console.log(max); // 9007199254740991 console.log(max + 1); // 9007199254740992 console.log(max + 2); // 9007199254740992 console.log(BigInt(max)); // 9007199254740991n console.log(BigInt(max) + BigInt(1)); // 9007199254740992n console.log(BigInt(max) + BigInt(2)); // 9007199254740993n
6.7 ES11-绝对全局对象globalThis
在html页面中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>ES11-绝对全局对象globalThis</title> </head> <body> <script> console.log(globalThis); </script> </body> </html>
输出结果
在node运行中
鉴定完毕,欢迎友友们一起交流学习!