ES6~ES9
ES6
1. let
1.1 let 变量声明及声明特性
let 用来声明变量,具有以下特性:
一、相较于 var ,let 变量不能重复声明
let a = 'a'; let a = 'a'; // 此时会报错
二、块级作用域(es5 中共有三种作用域:全局、函数、eval),即 let 定义的变量只在块级作用域内有效
{ let a = 'a'; } console.log(a); // is not defined
三、不存在变量提升
console.log(a); // cannot access 'a' before initialization let a = 'a';
四、不影响作用域链
{ let a = 'a'; function func(){ console.log(a); } func(); }
1.2 let 经典案例实践
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>切换颜色</title> <style> body{ margin: 0; padding: 0; background: #ccc; } h2{ margin: 10px; font-size: 40px; } .item{ display: flex; float: left; margin: 20px; border: 2px solid #000; width: 200px; height: 100px; background: #fff; } </style> </head> <body> <h2> 点击切换颜色 </h2> <div class="item"></div> <div class="item"></div> <div class="item"></div> <script> var items = document.getElementsByClassName('item'); /* for(var i = 0; i < items.length; i++){ items[i].onclick = function(){ this.style.background = 'pink'; } } */ //使用 let 代替上述 Code for(let i = 0; i < items.length; i++){ items[i].onclick = function(){ items[i].style.background = 'pink'; } } </script> </body> </html>
2. const
2.1 const 变量声明及声明特性
一、必须要赋初始值
二、一般常量使用大写(非必须)
三、常量的值不能修改
四、块级作用域
五、对于数组和对象的元素修改不算对常量的修改,不会报错
const TEAM = ['a', 'b']; TEAM.push('c'); // TEAM = 100; 这句话会报错
3.变量的解构赋值
ES6 允许按照一定模式从数组和对象中提取一些值,对变量进行赋值
3.1数组的解构
const arr = ['a', 'b', 'c', 'd']; // 定义四个变量,依次对应上面数组的值 let [A, B, C, D] = arr; console.log(A); console.log(B); console.log(C); console.log(D);
3.2对象的解构
const obj = { str: 'abc', num: 25, fun: function(){ console.log("Output"); } } // 与上面的 Code 格式相同,都要使用花括号 let {str, num, fun} = obj; console.log(str); console.log(num); console.log(fun); fun(); /* let {fun} = obj; fun(); */
4.模板字符串
一、声明上,相比 ES5,ES6 引入了新的字符串声明符号——反引号,与单双引号区别不大。
二、反引号中的内容可以直接出现换行符,举例,
let str = `abc def ghi`; console.log(str);
三、变量拼接
let s1 = "Hello,"; let s2 = `${s1}World!`; console.log(s2);
5.对象的简化写法
ES6 允许在大括号里面直接写入变量和函数,作为对象的属性和方法。
let name = "user"; let func = function(){ console.log("abc"); } const obj = { name, func } console.log(obj);
还有方法声明的简化,
const obj1 = { name: "abc", improve: function(){ console.log("abc"); } } // 以下为简化版 const obj2 = { name: "def", improve(){ console.log("def"); } }
6.箭头函数
6.1箭头函数及声明特点
ES6 允许使用箭头(=>)定义函数。
let func = (a, b) => { return a + b; } func(1, 1);
箭头函数的特性:
一、this 是静态的,始终指向函数声明时所在作用域下的 this 的值。
function getName1(){ console.log(this.name); } let getName2 = () => { console.log(this.name); } window.name = "abc"; const obj = { name: "def" } // 直接调用函数 getName1(); //> abc getName2(); //> abc //call 方法调用 getName1.call(obj); //> def getName2.call(obj); //> abc
二、不能作为构造函数实例化对象
let Person = (name, age) => { this.name = name; this.age = age; } let me = new Person('abc', 20); console.log(me); // 报错
三、不能使用 arguments 变量(该变量一般用来保存实参)
四、箭头函数简写
(1)当形参有且仅有一个时,可以省略小括号;
let add = n => { return n + n; } console.log(add(1));
(2)当代码体仅有一条语句时,可以同时省略花括号和 return 语句;
let pow = n => n*n; console.log(pow(2));
6.2箭头函数的实践与应用
例一,点击 div 2s 后变色
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> body{ margin: 0; padding: 0; background: #ccc; } div{ width: 200px; height: 200px; background: #58a; } </style> </head> <body> <div id="ad"></div> <script> let ad = document.getElementById('ad'); ad.addEventListener("click", function(){ /* 方法一 let _this = this; setTimeout(function(){ _this.style.background = 'pink'; }, 2000); */ setTimeout(() => { this.style.background = 'pink'; }, 2000); }); </script> </body> </html>
例二,从数组中返回偶数元素
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> body{ margin: 0; padding: 0; background: #ccc; } div{ width: 200px; height: 200px; background: #58a; } </style> </head> <body> <div id="ad"></div> <script> let ad = document.getElementById('ad'); ad.addEventListener("click", function(){ const arr = [1, 6, 9, 10, 100, 25]; /* 方法一 const result = arr.filter(function(item){ if(item % 2 === 0){ return true; }else{ return false; } }); */ const result = arr.filter(item => item % 2 === 0); console.log(result); }); </script> </body> </html>
由此可得以下结论,
一、箭头函数适合与 this 无关的回调(定时器、数组等)
二、箭头函数不适合与 this 有关的回调(DOM 事件回调、对象方法等)
7.函数参数的默认值设置
7.1形参的初始值
function add(a, b, c){ return a + b + c; } let result1 = add(1, 2); console.log(result1); //> NaN function sub(a, b, c = 10){ return c - b - a; } let result2 = sub(1, 2); console.log(result2); //> 7
带默认参数的函数的位置一般靠后。
7.2与解构赋值结合
function connect({host="127.0.0.1", username, password, port}){ console.log(host); console.log(username); console.log(password); console.log(port); } connect({ // host: 'localhost', username: 'root', password: 'root', port: 3306 })
8. rest 参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,
function date1(){ console.log(arguments); } date('abc','def','ghi'); // 对象 function date2(...args){ console.log(args); } date('abc','def','ghi'); // 数组
利用 rest 创造的数组就可以使用与数组相关的 API 方法,如 filter,some,every,map 等。
rest 参数必须要放到参数的最后,例如,
function fun(a, b, ...args){ console.log(a); //> 1 console.log(b); //> 2 console.log(args); //> [3, 4, 5, 6] } fun(1, 2, 3, 4, 5, 6);
9.扩展运算符( ... )
扩展运算符 ... 能将数组转换为逗号分隔的参数序列
const arr = ['abc', 'def', 'ghi']; function fun(){ console.log(arguments); } fun(arr); //> 0: ['abc', 'def', 'ghi'] fun(...arr); //> 0: 'abc' 1: 'def' 2: 'ghi'
应用:
一、数组的合并
const arr1 = ['abc', 'def']; const arr2 = ['123', '456']; //ES5 const arr3 = arr1.concat(arr2); console.log(arr3); //ES6 const arr4 = [...arr1, ...arr2]; console.log(arr4);
二、数组的克隆
const arr1 = ['abc', 'def']; const arr2 = [...arr1];
-----》(引用数据问题?)《-----
三、将伪数组转换为真正的数组
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div></div> <div></div> <div></div> <script> const divs = document.querySelectorAll('div') console.log(divs); // 对象 const divArr = [...divs]; console.log(divArr); // 数组 </script> </body> </html>
10. Symbol 数据类型
ES6 引入了一种新的原始数据类型——Symbol,用来表示独一无二的值。
它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
10.1特点
一、Symbol 的值是唯一的,用来解决命名冲突问题
二、Symbol 的值不能与其他数据进行运算
三、Symbol 定义的对象属性不能使用 for...in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
10.2创建 Symbol
// 方法一,此时 Symbol 是一个函数 let s1 = Symbol(); console.log(s1, typeof s1); //> Symbol() 'symbol' let s2 = Symbol('abc'); let s3 = Symbol('abc'); console.log(s2 === s3); //> false // 方法二,此时 Symbol 是一个对象 let s4 = Symbol.for('abc'); console.log(s4, typeof s4); //> Symbol(abc) 'symbol' let s5 = Symbol.for('abc'); let s6 = Symbol.for('abc'); console.log(s5 === s6); //> true
总结:JavaScript 的七种数据类型 “USONB”
U:undefined S:string symbol O:object N:null number B:boolean
10.3给对象添加 Symbol 类型的属性
let obj = { name: 'abc' }; let ud = { up: Symbol(), down: Symbol() }; obj[ud.up] = function(){ console.log("up"); } obj[ud.down] = function(){ console.log("down"); }
let obj = { name: 'abc', [Symbol('say')]: function(){ console.log("def"); }, [Symbol('sby')]: function(){ console.log("ghi"); } } console.log(obj);
10.4 Symbol 内置值
所谓内置值,即为 Symbol 对象的属性(共 11 个)。
内置值 | 描述 |
---|---|
Symbol.hasInstance | 当其他对象调用 instanceof 运算符,判断是否为该对象的实例时,回调用这个方法 |
Symbol.isConcatSpreadable | 对象的该属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat() 时,是否可以展开 |
Symbol.unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除 |
Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值 |
Symbol.replace | 当该对象被 str.replace(Object) 方法调用时,会返回该方法的返回值 |
Symbol.search | 当该对象被 str.search(Object) 方法调用时,会返回该方法的返回值 |
Symbol.split | 当该对象被 str.split(Object) 方法调用时,会返回该方法的返回值 |
Symbol.iterator | 对象进行 for...of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值,会调用这个方法,返回该对象对应的原始类型值 |
Symbol.toStringTag | 在该对象上面调用 toString 方法时,返回该方法的返回值 |
Symbol.species | 创建衍生对象时,会使用该属性 |
10.4.1 Symbol.hasInstance
class Person{ static [Symbol.hasInstance](param){ console.log(param); console.log("abc"); //> abc //return true; } } let o = {}; console.log(o instanceof Person); //> false
10.4.2 Symbol.isConcatSpreadable
const arr1 = [1, 2, 3]; const arr2 = [4, 5, 6]; arr2[Symbol.isConcatSpreadable] = false; //不可展开 const arr3 = arr1.concat(arr2); console.log(arr3); //> [1, 2, 3, [4, 5, 6]] console.log(arr3.length); //> 4
11.迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
12.生成器
13. Promise*
Promise 是 ES6 引入异步编程的新解决方案。
语法上,Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
(关于异步编程,主要指的是 IO 的代码,包括文件IO、数据库IO、网络请求IO等)
13.1实例化 Promise 对象
对象的三种状态:初始化,成功,失败。
const p = new Promise(function(resolve, reject){ // 封装异步操作 setTimeout(function(){ let data = '数据库中的用户数据'; resolve(data); let err = '数据读取失败'; reject(err); }, 1000); }); // 调用 Promise 对象的 then 方法 p.then(function(value){ // 异步成功执行 console.log(value); }, function(reason){ // 异步失败执行 console.error(reason); });
13.2使用 Promise 封装读取文件
(注:涉及 Node.js)
// 1.引入 fs 模块 const fs = require('fs'); // 2.调用方法 fs.readFile('./aha/aaa.md', (err, data)=>{ //err:报错 data:读取结果 if(err) throw err; console.log(data); //> <Buffer 61 61 61 09 e4 b8 80 e4 ba 8c e4 b8 89> console.log(data.toString()); //> aaa 一二三 }); // 3.使用 Promise 封装 const p = new Promise(function(resolve, reject){ fs.readFile("./aha/aaa.md", (err, data)=>{ if(err) reject(err); resolve(data); }); }); p.then(function(value){ console.log(value.toString()); //> aaa 一二三 }, function(reason){ console.log("读取失败!!"); });
(上述 Code 在 PowerShell 中,使用 node FileName.js 命令调试)
13.3使用 Promise 封装 Ajax 请求
const p = new Promise((resolve, reject)=>{ // 1.创建对象 const xhr = new XMLHttpRequest(); // 2.初始化 xhr.open("GET", "https://api.apiopen.top/getJoke"); // 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(reason){ console.err(reason); });
13.4 Promise.prototype.then 方法
const p = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('用户数据'); }, 1000) }); // 调用 then 方法 const result = p.then(value => { console.log(value); }, reason => { console.log(reason); }); console.log(result);
then 方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定。
一、如果回调函数中返回结果是非 Promise 类型的数据,此时状态为成功。
二、如果是 Promise 对象,则按该 Promise 的情况返回成功或失败。
三、抛出(throw)错误,此时状态为失败。
此时说明 then 方法可以链式调用。
13.5实践练习
多文件读取。
const fs = require("fs"); fs.readFile('./aaa.aaa', (err, data1)=>{ fs.readFile('./bbb.bbb', (err, data2)=>{ fs.readFile('./ccc.ccc', (err, data3)=>{ let result = `${data1}\r\n${data2}\r\n${data3}`; console.log(result); }); }); }); // 使用 Promise 实现 const p = new Promise((resolve, reject) => { fs.readFile("./aaa.aaa", (err, data) => { resovle(data); }); }); p.then(value => { console.log(value.toString()); return new Promise((resolve, reject) => { fs.readFile("./bbb.bbb", (err, data) => { resolve([value, data]); }); }) }).then(value => { console.log(value.toString()); return new Promise((resolve, reject) => { fs.readFile("./ccc.ccc", (err, data) => { // 压入 value.push(data); resolve(value); }); }) }).then(value => { console.log(value.join('\r\n')); })
13.6 catch 方法
const p = new Promise((resolve, reject) => { setTimeout(() => { reject("ERROR"); }, 1000) }); p.then(function(value){ console.log(value); }, function(reason){ console.err(reason); }) p.catch(function(reason){ console.warn(reason); })
14. Set
14.1集合 Set 的创建与方法
ES6 提供了新的数据结构——Set(集合),它类似于数组,但成员的值是唯一的。
集合实现了 iterator 接口,所有可以使用扩展运算符与for...of遍历。
方法 | 描述 |
---|---|
size | 返回集合的元素个数 |
add | 增加一个新元素并返回当前集合 |
delete | 删除元素并返回当前集合 |
has | 检测集合中是否包含某个元素并返回 boolean 值 |
clear | 清空当前集合并返回 undefined |
let s = new Set(); console.log(typeof s); //> 'object' // Set 内可传入数组或可迭代数据 let s2 = new Set(['abc', 'def', 'abc']); console.log(s2); //> {'abc', 'def'} (会自动去重) console.log(s2.size); //> 2 s2.add('ghi'); console.log(s2); //> {'abc', 'def', 'ghi'} s2.delete('abc'); console.log(s2); //> {'def', 'ghi'} console.log(s2.has('def')); //> true s2.clear(); console.log(s2); //> undefined let s3 = new Set(['123', '456', '789']); // 遍历集合 for(let v of s3){ console.log(v); }
14.2集合 Set 的实践
14.2.1数组去重
let arr = [1, 2, 3, 4, 5, 2, 1]; let res = [...new Set(arr)]; console.log(res); //> [1, 2, 3, 4, 5]
14.2.2交集
let arr1 = [1, 2, 3, 4]; let arr2 = [8, 2, 9, 8]; /* let res = [...new Set(arr1)].filter(item => { let s2 = new Set(arr2); if(s2.has(item)){ return true; }else{ return false; } }); console.log(res); //> [2] */ let res = [...new Set(arr1)].filter(item => new Set(arr2).has(item)); console.log(res); //> [2]
14.2.3并集
let arr1 = [1, 2, 4]; let arr2 = [3, 5, 6]; let union = [...new Set([...arr1, ...arr2])]; console.log(union); //> [1, 2, 4, 3, 5, 6]
14.2.4差集
let arr1 = [1, 2, 3]; let arr2 = [1, 2, 4]; let res = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item))); console.log(res); //> [3]
15. Map
ES6 提供了 Map 数据结构,它类似于对象,也是键值的集合。
“键”的范围不局限于字符串。
Map 也实现了 iterator 接口,所有可以使用扩展运算符与for...of遍历。
方法 | 描述 |
---|---|
size | 返回 Map 的元素个数 |
set | 增加一个新元素,返回当前 Map |
get | 返回键名对象的键值 |
has | 检测 Map 中是否包含某个元素并返回 boolean 值 |
clear | 清空 Map 内所有元素并返回 undefined |
let m = new Map(); // 添加元素 m.set('name', 'abc'); m.set('change', function(){ console.log("123"); }); let key = { school: 'def' }; m.set(key, ['A', 'B']); console.log(m); // 元素个数 console.log(m.size); //> 3 // 删除元素 m.delete('name'); console.log(m); // 获取 console.log(m.get(key)); // 遍历 for(let v of m){ console.log(v); } // 清空 m.clear();
16. Class
17.数值扩展
17.1 Number.EPSILON
Number.EPSILON 是 JavaScript 表示的最小精度
console.log(0.1 + 0.2 === 0.3); //> false function equal(a, b){ if(Math.abs(a - b) < Number.EPSILON){ return true; }else{ return false; } } console.log(equal(0.1 + 0.2, 0.3)); //> true
17.2二、八、十、十六进制
//二进制 let b = 0b1010; console.log(b); //> 10 //八进制 let o = 0o1010; console.log(o); //> 520 //十进制 let d = 1010; console.log(d); //> 1010 //十六进制 let x = 0x1010; console.log(x); //> 4112
17.3 Number.isFinite
Number.isFinite 检测一个数是否为有限数
console.log(Number.isFinite(100)); //> true console.log(Number.isFinite(100/0)); //> false
17.4 Number.isNaN
Number.isNaN 检测一个数是否为 NaN
17.5字符串转整数 / 浮点数
Number.parseInt Number.parseFloat
console.log(Number.parseFloat('12.34aaa')); //> 12.34
17.6 Number.isInteger
Number.isInteger 检测一个数是否为整数
17.7 Math.trunc
Math.trunc 将数字的小数部分删除
17.8 Math.sign
Math.sign 检测一个数是正数、负数还是零
console.log(Math.sign(10)); //> 1 console.log(Math.sign(-10)); //> -1 console.log(Math.sign(0)); //> 0
18.对象方法的扩展
18.1 Object.is
Object.is 判断两个值是否完全相等
console.log(Object.is(1, 1)); //> true console.log(Object.is(1, 2)); //> false // 与 === 的区别 console.log(Object.is(NaN, NaN)); //> true console.log(NaN === NaN); //> false
18.2 Object.assign
Object.assign 对象的合并
const config1 = { host: 'localhost', port: 3306, user: 'name' }; const config2 = { host: 'xxx.com', port: 33060 }; // config2 覆盖 config1 console.log(Object.assign(config1, config2)); /* 输出结果: {host: 'xxx.com', port: 33060, user: 'name'} */
18.3关于原型对象
Object.setPrototypeOf 设置原型对象
Object.getPrototypeOf 获取原型对象
const obj1 = { a : 'abc' } const obj2 = { b : ['1', '2', '3'] } Object.setPrototypeOf(obj1, obj2); console.log(obj1); console.log(Object.getPrototypeOf(obj1));
19.模块化
模块化的优势是指将一个大的程序文件,拆分成许多小文件,然后将小文件组合秋来起来。
19.1好处
(1)防止命名冲突
(2)代码复用
(3)高维护性
19.2模块化规范产品
(1)CommonJS => NodeJS、Browserify
(2)AMD => requireJS
(3)CMD => seaJS
19.3 ES6 模块化语法
19.3.1 export 和 import
模块化功能主要由两个命令构成:export 和 import。
export 命令用于规定模块的对接口。(暴露)
import 命令用于输入其他模块提供的功能。(导入)
// File name: m1.js // 分别暴露 export let school = 'abc'; export function fun(){ console.log("output"); }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script type="module"> // 引入 m1.js 模块 import * as mdl from "./src/js/m1.js"; </script> </body> </html>
19.3.2暴露模块数据语法汇总
19.3.2.1分别暴露
// File name: m1.js export let school = 'abc'; export function fun(){ console.log("output"); }
19.3.2.2统一暴露
// File name: m2.js let school = 'abc'; function fun(){ console.log("output"); } export { school, fun };
19.3.2.3默认暴露
// File name: m3.js export default{ school: 'abc', change: function(){ console.log("output"); } }
19.3.3导入模块数据语法汇总
19.3.3.1通用导入
<script type="module"> import * as m1 from "./src/js/m1.js"; </script>
19.3.3.2解构赋值形式导入
<script type="module"> import { school, fun } from "./src/js/m1.js"; // 变量重名处理方法 // 使用 as 将重名的键取别名化处理 import { school as school2, fun } from "./src/js/m2.js"; // 导入默认暴露的方法 import { default as m3 } from "./src/js/m3.js"; </script>
19.3.3.3简便形式导入(仅针对默认暴露)
<script type="module"> import m3 from "./src/js/m3.js"; </script>
19.3.4浏览器使用 ES6 模块化方式
通过新建 JavaScript 入口文件来导入模块。
// File name: app.js import * as m1 from "./m1.js";
<script src="./src/js/app.js" type="module"> </script>
19.3.5 babel 对 ES6 模块化代码的转换
转换:
babel src/js -d dist/js --presets=babel-preset-env
打包:
browserify dist/js/app.js -o dist/bundle.js
导入:
<script src="dist/bundle.js"></script>
19.4模块化引入 npm 包(涉及 jQuery,跳过)
npm i jquery
ES7
20. ES7 新特性
20.1 Array.Prototype.includes
includes 方法用来检测数组中是否包含某个元素并返回 boolean 值。
const a = ['a', 'b', 'c']; console.log(a.includes('a')); //> true console.log(a.includes('d')); //> false
20.2指数操作符
ES7 引入指数操作符( ** )用来实现幂运算,功能与 Math.pow 结果相同。
console.log(2**4); //> 16 console.log(4**0.5); //> 2
ES8
21. async 与 await
async 和 await 两种语法结合可以让异步代码像同步代码一样。
21.1 async 函数
一、async 函数的返回值为 Promise 对象
// async function fun(){ return 'abc'; } const result1 = fun(); console.log(result1); // async function fun(){ throw new Error("W"); } const result2 = fun(); console.log(result2); // async function fun(){ return new Promise((resolve, reject) => { resolve('Success'); }); } const result3 = fun(); console.log(result3); result3.then(value => { console.log(value); }, reason => { console.log(reason); })
(1)如果返回的结果不是一个 Promise 类型的对象,那么 Promise 的结果就是成功。
(2)当抛出错误时,Promise 就是失败。
(3)如果返回的结果是一个 Promise 类型的对象
二、Promise 对象的结果由 async 函数执行的返回值决定
21.2 await 表达式
一、await 必须写在 async 函数中
二、await 右侧的表达式一般为 Promise 对象
三、await 返回的是 Promise 成功的值
四、await 的 Promise 失败了,就会抛出异常,需要通过 try...catch 捕获处理
// 成功 const p = new Promise((resolve, reject) => { resolve("Success"); }); async function fun(){ let result = await p; console.log(result); } fun();
// 失败 const p = new Promise((resolve, reject) => { reject("Wrong"); }); async function fun(){ try{ let result = await p; console.log(result); }catch(e){ console.log(e); } } fun();
21.3 async 和 await 结合读取文件
const fs = require("fs"); function reada(){ return new Promise((resolve, reject) => { fs.readFile("./aaa.aaa", (err, data) => { if(err) reject(err); resovle(data); }) }) } function readb(){ return new Promise((resolve, reject) => { fs.readFile("./bbb.bbb", (err, data) => { if(err) reject(err); resovle(data); }) }) } function readc(){ return new Promise((resolve, reject) => { fs.readFile("./ccc.ccc", (err, data) => { if(err) reject(err); resovle(data); }) }) } async function fun(){ let aa = await reada(); let bb = await readb(); let cc = await readc(); console.log(aa.toString()); console.log(bb.toString()); console.log(cc.toString()); } fun();
21.4 async 和 await 封装 Ajax 请求
发送 Ajax 请求并返回 Promise 对象。
function sendAjax(url){ return new Promise((resolve, reject) => { // 1.创建对象 const xhr = new XMLHttpRequest(); // 2.初始化 xhr.open('GET', url); // 3.发送 xhr.send(); // 4.事件绑定 xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ if(x.status >=200 && x.status < 300){ resolve(xhr.response); }else{ reject(xhr.status); } } } }) } // Promise then 方法测试 sendAjax("https://api.apiopen.top/getJoke").then(value => { console.log(value); }, reason => { console.log(reason); }); // async 和 await 方法测试 async function fun(){ let result = await sendAjax("https://api.apiopen.top/getJoke"); console.log(result); } fun();
22.对象方法扩展
22.1 Object.values
Object.values() 方法返回一个给定对象的所有可枚举属性值的数组。
const obj = { name: 'abc', age: 20 }; // 获取对象所有键 console.log(Object.keys(obj)); // 获取对象所有键值 console.log(Object.values(obj));
22.2 Object.entries
Object.entries() 方法返回一个给定对象自身可遍历属性 [ key , value ] 的数组。
const obj = { name: 'abc', age: 20 }; console.log(Object.entries(obj));
由此可以看出,该方法有利于创建 Map 数据结构。
const obj = { name: 'abc', age: 20 }; const m = new Map(Object.entries(obj)) console.log(m);
22.3 Object.getOwnPropertyDescriptors
该方法返回指定对象所有自身属性的描述对象。
const obj = { name: 'abc', age: 20 }; console.log(Object.getOwnPropertyDescriptors(obj));
const obj = Object.create(null, { name: { //设置值 value: 'abc', //设置属性特性 writable: true, // 可写 configurable: true, // 可删 enumerable: true // 可枚举 } }); console.log(Object.getOwnPropertyDescriptors(obj));
ES9
23.扩展运算符与 rest 参数
ES9 为对象提供了像数组一样的扩展运算符和 rest 参数。
function connect({host, port, ...user}){ console.log(host); console.log(port); console.log(user); } connect({ host: '127.0.0.1', port: 3306, username: 'root', password: 'root' });
const obj1 = { a: 'a' } const obj2 = { b: 'b' } const obj3 = { c: 'c' } const tot = {...obj1, ...obj2, ...obj3}; console.log(tot);
24.正则扩展
24.1命名捕获分组
// 未进行命名捕获分组 let str = '<a href="https://www.xxx.com">xxx</a>'; // 提取 url 与标签文本 const reg = /<a href="(.*)">(.*)<\/a>/; // 执行 const result = reg.exec(str); console.log(result); // groups 是 undefined 状态 console.log(result[1]); //> https://www.xxx.com console.log(result[2]); //> xxx
// 进行命名捕获分组 let str = '<a href="https://www.xxx.com">xxx</a>'; const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/; const result = reg.exec(str); console.log(result); // groups 被定义 console.log(result.groups.url); //> https://www.xxx.com console.log(result.groups.text); //> xxx
24.2反向断言
断言:判断匹配结果正确与否。
let str = 'J123aaa456bbb'; // 正向断言 const reg1 = /\d+(?=b)/; const res1 = reg1.exec(str); console.log(res1); // 反向断言 const reg2 = /(?<=a)\d+/; const res2 = reg2.exec(str); console.log(res2);
24.3 dotAll 模式
dot 是指正则表达式中的元字符( . ),代表除换行符以外任意单个字符
let str = ` <ul> <li> <a>AAA</a> <p>aaa</p> </li> <li> <a>BBB</a> <p>bbb</p> </li> </ul>`; // g/s :模式修正符 // g: 全局匹配 // s: dot 匹配任意字符 const reg = /.<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs; let result; let arr = []; while(result = reg.exec(str)){ console.log(result); arr.push({ x: result[1], y: result[2] }); } console.log(arr);
编辑于 2022/9/17
-End-
本文作者:SRIGT
本文链接:https://www.cnblogs.com/SRIGT/p/17583028.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?