ES简介 ES全称EcmaScript,是脚本语言的规范,而平时编写的JavaScript是EcmaScript的一种实现,所以ES新特性其实质就是JavaScript的新特性
ES6 let关键字 let a;let b, c, d;let e = 100 ;let f = 521 , g = 'iloveyou' , h = [];
let 关键字用来声明变量
let star = '罗志祥' ; let star = '小猪' ;
块儿级作用域 全局, 函数, eval(es5的严格模式)
{ let girl = '周扬青' ; var boy = '周扬' ; } console .log (girl); console .log (boy);
console .log (song); var song = '恋爱达人' ;console .log (song); let song = '恋爱达人' ;
{ let school = '尚硅谷' ; function fn ( ) { console .log (school); } fn (); }
实践案例
let items = document .getElementsByClassName ('item' );for (let i = 0 ; i < items.length ; i++) { items[i].onclick = function ( ) { items[i].style .background = 'pink' ; } } for (var i = 0 ; i < items.length ; i++) { items[i].onclick = function ( ) { this .style .background = 'pink' ; } } console .log (window .i )
const const声明常量
const SCHOOL = '尚硅谷' ;SCHOOL = 'ATGUIGU' ;
{ const PLAYER = 'UZI' ; } console .log (PLAYER );
const SCHOOL = '尚硅谷' ; const SCHOOL = 'ATGUIGU' ;
注意: 对象属性修改和数组元素变化不会出发 const 错误
const TEAM = ['UZI' , 'MXLG' , 'Ming' , 'Letme' ];TEAM .push ('Meiko' ); TEAM = 100 ;
应用场景:声明对象类型使用 const,非对象类型声明选择 let
变量的解构赋值 解构赋值: ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值
数组的解构 const F4 = ['小沈阳' , '刘能' , '赵四' , '宋小宝' ];let [xiao, liu, zhao, song] = F4 ;console .log (xiao); console .log (song);
对象的解构 const zhao = { name : '赵本山' , age : '不详' , xiaopin : function ( ) { console .log ("我可以演小品" ); } }; let { name, age, xiaopin } = zhao;console .log (name); xiaopin ();
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
模板字符串 模板字符串(template string): 是增强版的字符串,用反引号(`)标识ES6 引入新的声明字符串的方式 ```` ‘’ “”
字符串中可以出现换行符 let str = `<ul> <li>沈腾</li> <li>玛丽</li> <li>魏翔</li> <li>艾伦</li> </ul>` ;let str = '<ul>' + '<li>' + 沈腾 + '</li>' + '<li>' + 玛丽 + '</li>' + '</ul>'
可以使用 ${xxx} 形式输出变量 let lovest = '魏翔' ;let out = `${lovest} 是我心目中最搞笑的演员!!` ;
注意:当遇到字符串与变量拼接的情况使用模板字符串
简化对象写法 ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
let name = '尚硅谷' ;let change = function ( ) { console .log ('我们可以改变你!!' ); } const school = { name, change, improve ( ) { console .log ("我们可以提高你的技能" ); } } console .log (school);
箭头函数 「箭头」(=>)定义函数 let fn = function ( ) {} let fn = (a, b ) => { return a + b; } let result = fn (1 , 2 );console .log (result);
箭头函数 this 指向函数声明时所在作用域下 this 的值,this是静态的
function getName ( ) { console .log (this .name ); } let getName2 = ( ) => { console .log (this .name ); } window .name = '尚硅谷' ;const school = { name : "ATGUIGU" } getName (); getName2 (); getName.call (school); getName2.call (school);
let Person = (name, age ) => { this .name = name; this .age = age; } let me = new Person ('xiao' , 30 );
let fn = ( ) => { console .log (arguments ); } fn (1 , 2 , 3 );
箭头函数的简写
省略小括号, 当形参有且只有一个的时候
省略花括号, 当代码体只有一条语句的时候, 花括号可以省略,return 必须省略,函数的返回值为该条语句的执行结果
let fn2 = num => { return num * 10 ; }; let pow = n => n * n;console .log (pow (8 ));
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适
箭头函数适合与 this 无关的回调: 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调: 事件回调, 对象的方法
const obj = { name : 'lili' , getName : function ( ){ this .name ; }, getName1 : () => { this .name ; } }
箭头函数实践
let ad = document .getElementById ('ad' );ad.addEventListener ("click" , function ( ) { let _this = this ; setTimeout (function ( ) { console .log (this ); _this.style .background = 'pink' ; }, 2000 ); }); ad.addEventListener ("click" , function ( ) { setTimeout (() => { this .style .background = 'pink' ; }, 2000 ); });
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);
函数参数的默认值设置
形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add (a,b,c=10 ) { return a + b + c; } let result = add (1 ,2 );console .log (result)
function connect ({host="127.0.0.1" , username, password, port} ){ console .log (host) console .log (username) console .log (password) console .log (port) } connect ({ username : 'root' , password : 'root' , port : 3306 })
rest 参数 形式为"…变量名"
,
位置:函数声明的形参的位置
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
function date ( ){ console .log (arguments ); } date ('白芷' ,'阿娇' ,'思慧' );function add (...args ){ console .log (args); } add (1 ,2 ,3 ,4 ,5 );function minus (a,b,...args ){ console .log (a,b,args); } minus (100 ,1 ,2 ,3 ,4 ,5 ,19 );
rest参数
只包括那些没有给出名称的参数
,arguments
包含所有参数
arguments 对象
不是真正的数组,而rest
参数是数组实例
,可以直接应用sort, map, forEach, pop等方法
arguments 对象拥有一些自己额外的功能
spread 扩展运算符 扩展运算符 『…』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』,对数组进行解包,它好比 rest 参数的逆运算
const tfboys = ['易烊千玺' ,'王源' ,'王俊凯' ]; function chunwan ( ){ console .log (arguments ); } chunwan (...tfboys);
扩展运算符应用
const kuaizi = ['王太利' ,'肖央' ];const fenghuang = ['曾毅' ,'玲花' ];const zuixuanxiaopingguo = kuaizi.concat (fenghuang); const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];console .log (zuixuanxiaopingguo);
const sanzhihua = ['E' ,'G' ,'M' ];const sanyecao = [...sanzhihua];
const divs = document .querySelectorAll ('div' );console .log (divs); const divArr = [...divs];console .log (divArr);
Symbol Symbol 基本使用 ES6 引入了一种新的原始数据类型 Symbol
,表示独一无二的值
。它是JavaScript 语言的第七
种数据类型,是一种类似于字符串
的数据类型。
Symbol 特点
Symbol 的值是唯一
的,用来解决命名冲突
的问题
Symbol 值不能与其他数据
进行运算
Symbol 定义的对象属性
不能使用for…in
循环遍历 ,但是可以使用Reflect.ownKeys
来获取对象的所有键名
let s1 = Symbol ();console .log (s1, typeof s1); let s2 = Symbol ('尚硅谷' ); let s3 = Symbol ('尚硅谷' );console .log (s2 === s3); let s4 = Symbol .for ('尚硅谷' );let s5 = Symbol .for ('尚硅谷' );console .log (s4 === s5); let result = s1 + 100 ;
Symbol 创建对象属性 使用场景:给对象添加属性和方法
let game = { name :'俄罗斯方块' , up : function ( ){}, down : function ( ){} }; let methods = { up : Symbol (), down : Symbol () }; game[methods.up ] = function ( ){ console .log ("我可以改变形状" ); } game[methods.down ] = function ( ){ console .log ("我可以快速下降!!" ); } console .log (game);console .log (Reflect .ownKeys (game)) game[Reflect .ownKeys (game)[3 ]]() game[Reflect .ownKeys (game)[4 ]]() let youxi = { name :"狼人杀" , [Symbol ('say' )]: function ( ){ console .log ("我可以发言" ) }, [Symbol ('zibao' )]: function ( ){ console .log ('我可以自爆' ); } } const a = Object .getOwnPropertySymbols (youxi); youxi[a[0 ]](); youxi[a[1 ]](); let up1 = Symbol ();let down1 = Symbol ();let game1 = { name : 'YY' , up1 ( ) { console .log (1 ); }, down1 ( ) { console .log (2 ); }, [up1]() { console .log ('向上' ); }, [down1]() { console .log ('向下' ); } } game1[up1](); game1[down1]();
迭代器 Iterator 迭代器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 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 xiyou = ['唐僧' ,'孙悟空' ,'猪八戒' ,'沙僧' ];for (let v of xiyou){ console .log (v); } for (let v in xiyou){ console .log (v); } let iterator = xiyou[Symbol .iterator ]();console .log (iterator.next ()); console .log (iterator.next ()); console .log (iterator.next ()); console .log (iterator.next ()); console .log (iterator.next ()); console .log (iterator.next ());
iterator 接口:就是对象里面的一个属性,属性名字叫Symbol.iterator
注: 需要自定义遍历数据的时候,要想到迭代器。
Iterator自定义遍历数据
for…of遍历,每次返回结果是对象里属性的数组中的成员const banji = { name : "终极一班" , stus : [ 'xiaoming' , 'xiaoning' , 'xiaotian' , 'knight' ], [Symbol .iterator ]() { let index = 0 ; let _this = this ; return { next : function ( ) { if (index < _this.stus .length ) { const result = { value : _this.stus [index], done : false }; index++; return result; }else { return {value : undefined , done : true }; } } } } } for (let v of banji) { console .log (v); }
生成器 生成器函数声明和调用 生成器函数: 是 ES6 提供的一种异步
编程解决方案,语法行为与传统函数完全不同
代码说明:
*
的位置没有限制
生成器函数返回的结果是迭代器对象
,调用迭代器对象的 next 方法
可以得到yield 语句后的值
yield
相当于函数的暂停标记
,也可以认为是函数的分隔符
,每调用一次next方法
,执行一段代码
next方法
可以传递实参
,作为 上一个yield语句的返回值
function * gen ( ){ console .log (111 ); yield '一只没有耳朵' ; console .log (222 ); yield '一只没有尾部' ; console .log (333 ); yield '真奇怪' ; console .log (444 ); } let iterator = gen ();for (let v of gen ()){ console .log (v); }
生成器函数参数 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 ()); console .log (iterator.next ('BBB' )); console .log (iterator.next ('CCC' ));console .log (iterator.next ('DDD' ));
生成器函数实例
1s 后控制台输出 111 2s后输出 222 3s后输出 333
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 ); iterator.next (); },3000 ) } function * gen ( ){ yield one (); yield two (); yield three (); } let iterator = gen ();iterator.next ();
function getUsers ( ){ setTimeout (()=> { let data = '用户数据' ; iterator.next (data); }, 1000 ); } function getOrders ( ){ setTimeout (()=> { console .log (users) let data = '订单数据' ; iterator.next (data); }, 1000 ) } function getGoods ( ){ setTimeout (()=> { let data = '商品数据' ; iterator.next (data); }, 1000 ) } function * gen ( ){ let users = yield getUsers (); let orders = yield getOrders (users); console .log (orders) let goods = yield getGoods (); } let iterator = gen ();iterator.next ();
Promise Promise基本语法 Promise 是 ES6 引入的异步编程
的新解决方案。语法上 Promise 是一个构造函数
,用来封装异步操作并可以获取其成功
或失败
的结果
const p = new Promise (function (resolve, reject ){ setTimeout (function ( ){ let data = '数据库中的用户数据' ; resolve (data); }, 1000 ); }); p.then (function (value ){ console .log (value); }, function (reason ){ console .error (reason); })
Promise封装读取文件
读取resources文件夹下的为学.md文件,在控制台输出
const fs = require ('fs' );fs.readFile ('./resources/为学.md' , (err, data )=> { if (err) throw err; console .log (data.toString ()); }); const p = new Promise (function (resolve, reject ){ fs.readFile ("./resources/为学.mda" , (err, data )=> { if (err) reject (err); resolve (data); }); }); p.then (function (value ){ console .log (value.toString ()); }, function (reason ){ console .log ("读取失败!!" ); });
Promise封装AJAX
const p = new Promise ((resolve, reject ) => { const xhr = new XMLHttpRequest (); xhr.open ("GET" , "https://api.apiopen.top/getJ" ); xhr.send (); xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ) { if (xhr.status >= 200 && xhr.status < 300 ) { resolve (xhr.response ); } else { reject (xhr.status ); } } } }) p.then (function (value ){ console .log (value); }, function (reason ){ console .error (reason); });
Promise.prototype.then then方法
的返回结果是 Promise 对象
, 对象状态
由回调函数的执行结果
决定
const p = new Promise ((resolve, reject )=> { setTimeout (()=> { resolve ('用户数据' ); }, 1000 ) }); const result = p.then (value => { console .log (value); throw '出错啦!' ; }, reason => { console .warn (reason); }); console .log (result); p.then (value => { }).then (value => { });
实践-读取多个文件
const fs = require ("fs" );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 ('\r\n' )); });
Promise.prototype.catch const p = new Promise ((resolve, reject )=> { setTimeout (()=> { reject ("出错啦!" ); }, 1000 ) }); p.catch (function (reason ){ console .warn (reason); });
集合Set 集合介绍 ES6 提供了新的数据结构 Set(集合
)。它类似于数组
,但成员的值都是唯 一
的,集合实现了 iterator 接口,所以可以使用『扩展运算符』
和『for…of…』
进 行遍历。 集合的属性和方法:
size 返回集合的元素个数
add 增加一个新元素,返回当前集合
delete 删除元素,返回 boolean 值
has 检测集合中是否包含某个元素,返回 boolean 值
clear 清空集合,返回
let s = new Set ();let s2 = new Set (['大事儿' ,'小事儿' ,'好事儿' ,'坏事儿' ,'小事儿' ]);console .log (...s2) for (let v of s2){ console .log (v); }
Set实践 let arr = [1 ,2 ,3 ,4 ,5 ,4 ,3 ,2 ,1 ];let arr2 = [4 ,5 ,6 ,5 ,6 ];let diff = [...new Set (arr)].filter (item => !(new Set (arr2).has (item)));console .log (diff);
Map ES6 提供了 Map 数据结构
。它类似于对象
,也是键值对
的集合。但是“键”
的范围不限于字符串
,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口
,所以可以使用『扩展运算符』
和『for…of…』
进行遍历。 Map 的属性和方法:
size 返回 Map 的元素个数
set 增加一个新元素,返回当前 Map
get 返回键名对象的键值
has 检测 Map 中是否包含某个元素,返回 boolean 值
clear 清空集合,返回 undefined
delete 根据键名删除
let m = new Map ();m.set ('name' ,'尚硅谷' ); m.set ('change' , function ( ){ console .log ("我们可以改变你!!" ); }); let key = { school : 'ATGUIGU' }; m.set (key, ['北京' ,'上海' ,'深圳' ]); {key : {school : 'ATGUIGU' }, value : ['北京' ,'上海' ,'深圳' ]} for (let v of m){ console .log (v); }
class 类 ES6 提供了更接近传统语言的写法,引入了 Class(类)
这个概念,作为对象的模板。通过 class 关键字
,可以定义类
。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。 知识点:
class 声明类
constructor 定义构造函数初始化
extends 继承父类
super 调用父级构造方法
static 定义静态方法和属性
父类方法可以重写
class介绍 function Phone (brand, price ){ this .brand = brand; this .price = price; } Phone .prototype .call = function ( ){ console .log ("我可以打电话!!" ); } let Huawei = new Phone ('华为' , 5999 );Huawei .call ();console .log (Huawei );class Shouji { constructor (brand, price ){ this .brand = brand; this .price = price; } call ( ){ console .log ("我可以打电话!!" ); } } let onePlus = new Shouji ("1+" , 1999 );console .log (onePlus)
class静态成员 function Phone ( ){}Phone .name = '手机' ;Phone .change = function ( ){ console .log ("我可以改变世界" ); } Phone .prototype .size = '5.5inch' ;let nokia = new Phone ();console .log (nokia.name ); console .log (nokia.size ); class Phone { static name = '手机' ; static change ( ){ console .log ("我可以改变世界" ); } } let nokia = new Phone ();console .log (nokia.name ); console .log (Phone .name );
ES5构造函数继承 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 .size = size; } SmartPhone .prototype = new Phone ;SmartPhone .prototype .constructor = SmartPhone ; SmartPhone .prototype .photo = function ( ){ console .log ("我可以拍照" ) } SmartPhone .prototype .playGame = function ( ){ console .log ("我可以玩游戏" ); } const chuizi = new SmartPhone ('锤子' ,2499 ,'黑色' ,'5.5inch' );console .log (chuizi);
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); this .color = color; this .size = size; } photo ( ){ console .log ("拍照" ); } playGame ( ){ console .log ("玩游戏" ); } call ( ){ console .log ('我可以进行视频通话' ); } static connect ( ){ console .log ('我可以建立连接' ) } } const xiaomi = new SmartPhone ('小米' ,799 ,'黑色' ,'4.7inch' );xiaomi.playGame (); xiaomi.call (); SmartPhone .connect ();
class的get和set class Phone { get price (){ console .log ("价格属性被读取了" ); return 'iloveyou' ; } set price (newVal ){ console .log (newVal); console .log ('价格属性被修改了' ); } } let s = new Phone ();console .log (s.price ); s.price = 'free' ;
ES6的数值扩展 function equal (a, b ){ if (Math .abs (a-b) < Number .EPSILON ){ return true ; }else { return false ; } } console .log (0.1 + 0.2 === 0.3 ); console .log (equal (0.1 + 0.2 , 0.3 )) let b = 0b1010 ; let o = 0o777 ; let d = 100 ; let x = 0xff ; console .log (Number .isFinite (100 )); console .log (Number .isFinite (100 /0 )); console .log (Number .isFinite (Infinity )); console .log (Number .isNaN (123 )); console .log (Number .parseInt ('5211314love' )); console .log (Number .parseFloat ('3.1415926神奇' )); console .log (Number .isInteger (5 )); console .log (Math .trunc (3.5 )); console .log (Math .sign (100 )); console .log (Math .sign (0 )); console .log (Math .sign (-20000 ));
ES6的对象方法扩展 console .log (Object .is (120 , 120 )); console .log (Object .is (NaN , NaN )); console .log (Object .is (+0 , -0 )); console .log (Object .is (+0 , 0 )); console .log (NaN === NaN ); console .log (+0 === -0 ); true const config1 = { host : 'localhost' , port : 3306 , name : 'root' , pass : 'root' , test : 'test' }; const config2 = { host : 'http://atguigu.com' , port : 33060 , name : 'atguigu.com' , pass : 'iloveyou' , test2 : 'test2' } console .log (Object .assign (config1, config2));const school = { name : '尚硅谷' } const cities = { xiaoqu : ['北京' ,'上海' ,'深圳' ] } Object .setPrototypeOf (school, cities); console .log (Object .getPrototypeOf (school)); console .log (school);
模块化 模块化介绍 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来 模块化的优势有以下几点:
ES6 之前的模块化规范有:
CommonJS => NodeJS、Browserify
AMD => requireJS
CMD => seaJS
模块功能主要由两个命令构成:export 和 import
export let school = '尚硅谷' ;export function teach ( ) { console .log ("我们可以教给你开发技能" ); }
let school = '尚硅谷' ;function findJob ( ){ console .log ("我们可以帮助你找工作!!" ); } export {school, findJob};
export default { school : 'ATGUIGU' , change : function ( ){ console .log ("我们可以改变你!!" ); } }
import * as m1 from "./src/js/m1.js" ;m1.teach () import * as m2 from "./src/js/m2.js" ;m2.findJob () import * as m3 from "./src/js/m3.js" ;m3.default .change ()
import 命令用于输入其他模块提供的功能
通用的导入方式,* 引入文件中所有内容,放到对象中
解构赋值形式,as + 别名:给引入文件中的属性起别名,解决属性名重复问题
简便形式,针对默认暴露
import * as m1 from "./src/js/m1.js" ;import {school, teach} from "./src/js/m1.js" ;import {school as guigu, findJob} from "./src/js/m2.js" ;import {default as m3} from "./src/js/m3.js" ; teach ()m3.change () import m3 from "./src/js/m3.js" ;m3.change ()
babel对ES6模块化代码的转换
安装工具 npm i babel-cli(babel命令行工具) babel-preset-env(预设包) browserify(打包工具)(webpack) -D
编译 npx babel src/js -d dist/js –presets=babel-preset-env
打包 npx browserify dist/js/app.js -o dist/bundle.js
引入dist/bundle.js文件就可以src/js中文件的内容
ES7 Array.prototype.includes
includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
const mingzhu = ['西游记' ,'红楼梦' ,'三国演义' ,'水浒传' ];console .log (mingzhu.includes ('西游记' )); console .log (mingzhu.includes ('金瓶梅' )); console .log (mingzhu.indexOf ('红楼梦' ))
指数操作符
指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
console .log (2 ** 3 );console .log (Math .pow (2 , 3 ));
ES8 async 和 await async 和 await 两种语法结合可以让异步代码
像同步代码
一样
async 函数
async 函数的返回值为 promise 对象,
如果return直接返回字符串、数组等【不是Promise 类型的对象】, 那么返回的结果就是成功 Promise 对象
如果抛出错误, 返回的结果是一个失败的 Promise
返回的结果如果是一个 Promise 对象,promise 对象的结果由 async 函数执行的返回值决定
async function fn ( ){ return new Promise ((resolve, reject )=> { resolve ('成功的数据' ); }); } const result = fn ();result.then (value => { console .log (value); }, reason => { console .warn (reason); })
await 表达式
await 必须写在 async 函数中
await 右侧的表达式一般为 promise 对象
await 返回的是 promise 成功的值
await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
const p = new Promise ((resolve, reject ) => { reject ("失败啦!" ); }) async function main ( ) { try { let result = await p; console .log (result); } catch (e) { console .log (e); } } main ();
async和await结合实例
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 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 ();
function sendAJAX (url ) { return new Promise ((resolve, reject ) => { const x = new XMLHttpRequest (); x.open ('GET' , url); x.send (); x.onreadystatechange = function ( ) { if (x.readyState === 4 ) { if (x.status >= 200 && x.status < 300 ) { resolve (x.response ); }else { reject (x.status ); } } } }) } async function main ( ){ let result = await sendAJAX ("https://api.apiopen.top/getJoke" ); 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 ();
对象方法扩展 Object.values 和 Object.entries
Object.values()方法返回一个给定对象的所有可枚举属性值的数组
Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
const school = { name :"尚硅谷" , cities :['北京' ,'上海' ,'深圳' ], xueke : ['前端' ,'Java' ,'大数据' ,'运维' ] }; console .log (Object .keys (school)); console .log (Object .values (school)); ['尚硅谷' , ['北京' , '上海' , '深圳' ], ['前端' ,'Java' ,'大数据' ,'运维' ]]console .log (Object .entries (school)); [['name' , '尚硅谷' ], ['cities' , ['北京' , '上海' , '深圳' ]], ['xueke' , ['前端' ,'Java' ,'大数据' ,'运维' ]]]const m = new Map (Object .entries (school));console .log (m.get ('cities' ));
Object.getOwnPropertyDescriptors
const school = { name :"尚硅谷" , cities :['北京' ,'上海' ,'深圳' ], xueke : ['前端' ,'Java' ,'大数据' ,'运维' ] }; console .log (Object .getOwnPropertyDescriptors (school));const obj = Object .create (null , { name : { value : '尚硅谷' , writable : true , configurable : true , enumerable : true } });
ES9 Rest/Spread 属性 Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6
中只针对于数组
,在 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' , type : 'master' }); const skillOne = { q : '天音波' } const skillTwo = { w : '金钟罩' } const skillThree = { e : '天雷破' } const skillFour = { r : '猛龙摆尾' } const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};console .log (mangseng)
正则表达式 式命名捕获组 ES9 允许命名捕获组使用符号『?<name>』
,这样获取捕获结果可读性更强
let str = '<a href="http://www.atguigu.com">尚硅谷</a>' ;const reg = /<a href="(.*)">(.*)<\/a>/ ;const result = reg.exec (str);console .log (result[0 ]); console .log (result[1 ]); console .log (result[2 ]); let str1 = '<a href="http://www.atguigu.com">尚硅谷</a>' ;const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/ ;const result = reg.exec (str1);console .log (result.groups .url ); console .log (result.groups .text );
反向断言 ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。
let str = 'JS5211314你知道么555啦啦啦' ;const reg = /\d+(?=啦)/ ;const result = reg.exec (str);console .log (result[0 ]); const reg1 = /(?<=么)\d+/ ;const result1 = reg.exec (str);console .log (result1[0 ]);
dotAll 模式 正则表达式中点.
匹配除回车外的任何单字符
,标记『s』
改变这种行为,允许行终止符
出现
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>/g s;let result;let data = [];while (result = reg.exec (str)){ data.push ({title : result[1 ], time : result[2 ]}); } console .log (data);
ES10 Object.fromEntries 将二维数组转换为对象,与Object.entries互为逆运算
const result = Object .fromEntries ([ ['name' ,'尚硅谷' ], ['xueke' , 'Java,大数据,前端,云计算' ] ]); console .log (result) const m = new Map ();m.set ('name' ,'ATGUIGU' ); const result1 = Object .fromEntries (m);console .log (result1) const arr = Object .entries ({ name : "尚硅谷" }) console .log (arr); [['name' , '尚硅谷' ]]
trimStart 和 trimEnd
trimStart 清除字符串左侧空白的字符
trimEnd 清除字符串右侧空白的字符
let str = ' iloveyou ' ;console .log (str);console .log (str.trimStart ());console .log (str.trimEnd ());
Array.prototype.flat 与 flatMap 将多维数组转化为低位数组
const arr = [1 ,2 ,3 ,4 ,[5 ,6 ]];console .log (arr.flat ()); const arr1 = [1 ,2 ,3 ,4 ,[5 ,6 ,[7 ,8 ,9 ]]];console .log (arr1.flat (2 )); const arr2 = [1 ,2 ,3 ,4 ];const result1 = arr2.map (item => [item * 10 ]);console .log (result1); const result = arr2.flatMap (item => [item * 10 ]);console .log (result); [10 ,20 ,30 ,40 ];
Symbol.prototype.description 获取Symbol的字符串描述
let s = Symbol ('尚硅谷' );console .log (s.description );
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); console .log (this .#weight); } } const girl = new Person ('晓红' , 18 , '45kg' );console .log (girl.name ); console .log (girl.#age); console .log (girl.#weight); girl.intro ();
Promise.allSettled 返回的结果始终是成功(resolve)的,成功的值是每一个promise对象执行的结果的值和状态
const p1 = new Promise ((resolve, reject )=> { setTimeout (()=> { resolve ('商品数据 - 1' ); },1000 ) }); const p2 = new Promise ((resolve, reject )=> { setTimeout (()=> { reject ('出错啦!' ); },1000 ) }); const result = Promise .allSettled ([p1, p2]);console .log (result); const res = Promise .all ([p1, p2]);console .log (res);
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>/ sgconst result = str.matchAll (reg);for (let v of result){ console .log (v); } const arr = [...result];console .log (arr);
可选链操作符 符号:?.
,使用情况:获取对象层级较深
的属性值,解决层层判断的烦恼
function main (config ){ const dbHost = config?.db ?.host ; console .log (dbHost); } main ({ db : { host :'192.168.1.100' , username : 'root' }, cache : { host : '192.168.1.200' , username :'admin' } })
动态import加载 按需加载
export function hello ( ){ alert ('Hello' ); }
const btn = document .getElementById ('btn' );btn.onclick = function ( ){ import ('./hello.js' ).then (module => { module .hello (); }); }
BigInt 大整形 更大的数值运算 声明方式:在普通数字
后面加n
let n = 521n ;console .log (n, typeof (n)); let n = 123 ;console .log (BigInt (n)); console .log (BigInt (1.2 )); let max = Number .MAX_SAFE_INTEGER ; console .log (max);console .log (max + 1 );console .log (max + 2 );console .log (BigInt (max))console .log (BigInt (max) + BigInt (1 ))console .log (BigInt (max) + BigInt (2 ))
globalThis 始终指向全局对象