ES6-11
Let
声明变量
声明一个变量
let a;
声明多个个变量
let b,c,d;
赋予初始值
let e =100;
赋予多个初始值
let f = 521,g = 'iloveyou', h= [];
声明变量的特性
变量不能重复声明(报错),var可以
let a = 1;
let a = 2;
作用于块级作用域
变量只在代码块里面有效,出了代码块以外就无效,读取不到
ES5作用域分三种:全局、函数、eval
ES6新增块级作用域
实例:
{
let a =1;
}
if else while for 都属于块级作用域
console.log(a); 会报错:显示没有定义a;
不存在变量提升
变量提升:代码在执行之前会提前收集变量(var 还有函数)的属性,会提前声明且赋予初始值undefinded
例如:
console.log(a) ; 输出undefined,如果使用let定义a就会报错
var a = '11111';
不影响作用域链
{
let school = 111;
function fn(){
console.log(school);
}
fn();
}
调用fn函数,因为函数内没有school变量,会向上一级的作用域里面找school变量,所以说虽然let是块级作用域,但是不影响作用域链的效果
Const(常用数组和对象)
声明常量(值不可以修改的)
const a = 1111;
一定要赋予初始值
const a;会报要初始化的错误
常量的值不能修改
a = '12346';会报错
块级作用域
{
const gamer = ’大飞‘
}
console.log(gamer);报错找不到gamer
对数组和对象的元素值修改,不算做对常量的修改,不会报错
const team = ['111','222','333','444','555'];
team.push('6666');
常量team的值改变了,但地址没有发生改变
变量的解构赋值
const team = ['aaa','bbb','ccc','ddd','ffff'];
let {aaa,bbb,ccc,ddd,fff} = team
模板字符串(``)
let a = 'afasf'
let b = ${a}hgwsedfgsdg
对象简化写法
ES6允许大括号里面,直接写入变量和函数,作为对象的属性和方法
let name = 'aaa';
let change = function(){
console.log('gsdgaga');
}
const school = {
name,
change,
improve:function(){ //可以省略冒号和function improve(){}
console.log("dfgsdgsdgsd");
}
}
箭头函数
箭头函数适合与this无关的回调。定时器,数组的方法回调
箭头函数不适合与this有关的回调。事件源的回调,对象的方法
静态this值
this是静态的。this始终指向函数声明时所在作用域下(当前所在的上层作用域)的this的值
function getName(){
console.log(this.name);
}
let getName2 = ()=>{
console.log(this.name);
}
window.name = 'shanguigu';
const school = {
name: 'SHANGUIGU'
}
//直接调用
getName();
getName2();
//call方法调用
getName.call(school); 输出改变,为SHANGUIGU
getName2.call(school); 输出不改变,为shanguigu
箭头函数的this值是静态的,无论用什么方式去调用,this始终是指向箭头函数在声明时在作用域下的this值
扩展案例1:
let ad = document.getElementById('ad');
ad.addEventListener("click",function () {
// //需要保存this的值
// let _this = this;
// //定时器
// setTimeout(function () {
// //直接调用this其实是指向window
// _this.style.background = 'pink';
// },2000)
//定时器
setTimeout( ()=>{
this.style.background = 'pink';
},2000)
});
扩展案例2:
let numbers = [5, 12, 9, 130, 44];
// let filtered = numbers.filter(function (number) {
// if (number % 2 === 0 ){
// return true;
// }else {
// return false;
// }
// });
let filtered = numbers.filter(number => number %2 === 0 );
console.log(filtered);
不能作为构造实例化对象
let Person = (name,age) =>{
this.name = name;
this.age = age;
}
let me = Person('agdgs',34);
console.log(me); //报错Person is not a constructor
不能使用arguments变量
箭头函数的简写
第一种情况:省略小括号,当形参有且只有一个的时候
// let add = (n) =>{
// return n+n;
// }
let add = n =>{
return n+n;
}
console.log(add(9));
第二种情况:省略花括号,当代码体只有一条代码的时候
此时return必须省略,而且代码的执行结果就是函数的返回值
// let pow = n => {
// return n * n;
// }
// console.log(pow(9));
let pow = n => n * n;
console.log(pow(9));
rest参数(...标识符)
ES6引入rest参数
放于函数声明的形参位置
用于获取函数的实参,用来代替ES5的arguments获取参数方式
//rest 参数
function data(...args) {
console.log(...args);
}
data('aaa','bbb','ccc');
rest参数必须放到参数最后
function fn(a,b,...args) {
console.log(a);
console.log(b);
console.log(...args);
}
fn('aaa','bbb','ccc','ddd','eee');
arguments获取参数
function data() {
console.log(arguments);
}
data('aaa','bbb','ccc');
扩展运算符(...标识符)
能将[数组]转化为逗号分隔的[参数序列]
放于函数调用的实参里
数组合并
const shuzhu_a = ['aaa','bbb'];
const shuzhu_b = ['ccc','ddd'];
//传统方式
// const c = shuzhu_a.concat(shuzhu_b);
const c = [...shuzhu_a,...shuzhu_b];
console.log(c);
数组克隆
const shuzhu = ['e','g','m'];
const kelong = [...shuzhu];
console.log(kelong);
伪数组转数组
const weishuzhu = document.querySelectorAll('div');
const shuzhu = [...weishuzhu];
console.log(shuzhu);
Symbol
ES6引入了一种新的原始数据类型symbol,表示独一无二的值。它是JavaScript语言是第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
//创建Symbol,Symbol是函数
let s = Symbol();
let s1 = Symbol('尚硅谷');
let s2 = Symbol('尚硅谷');
//false
console.log(s1===s2);
//创建Symbol.for,此时Symbol是对象
//通过这种方式创建,可以通过描述字符串来得出唯一的Symbol值
let s3 = Symbol.for('尚硅谷');
let s4 = Symbol.for('尚硅谷');
//true
console.log(s3===s4);
Symbol使用场景
给对象添加方法
let game = {}
let methods = {
up:Symbol(),
down:Symbol()
}
game[methods.up] = function () {
console.log('change up');
}
game[methods.down] = function () {
console.log('change down');
}
console.log(game);
let game = {
name : 'nishuihan',
[Symbol('say')]:function() {
console.log('say');
},
[Symbol('tiequan')]:function() {
console.log('tiequan');
}
}
console.log(game);
Symbol内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。
class Person {
static [Symbol.hasInstance](){
console.log("我被用来检测类型");
}
}
let e = {}
console.log(e instanceof Person);
//输出:我被用来检测类型
//输出:false

迭代器
遍历器(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 xiaoshuo = ['西游记','三国演义','红楼梦','水浒传'];
//使用for...of是保留键值(西游记、三国演义、红楼梦、水浒传)来遍历数组
for (let v of xiaoshuo){
console.log(v);
}
//使用for...in是保留键名(0、1、2、3)遍历数组
Symbol迭代器接口(方法)遍历
//声明一个对象
const xiaoshuo = {
name:"小说",
novel:['西游记','三国演义','红楼梦','水浒传'],
//迭代器方法
[Symbol.iterator](){
//索引变量
let index = 0;
let _this = this;
//需要定义返回对象
return {
//第一次要调用对象的 next 方法
next : function () {
if (index < _this.novel.length){
//需要返回一个对象
const result = {value: _this.novel[index],done:false};
index++;
return result;
}else {
return {value: undefined,done: true};
}
}
};
}
};
//遍历上方对象
//正常遍历方式,但不符合面向对象的思想
// xiaoshuo.novel.forEach(result =>{
// console.log(result);
// });
for (let x of xiaoshuo) {
console.log(x);
}
生成器
生成器是一种函数,是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
实例1:
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数(node fs、ajax、mongodb)
//函数代码的分隔符
function * gen() {
// console.log(111);
yield 111;
// console.log(2222);
yield 222;
// console.log(3333);
yield 333;
// console.log(4444);
yield 444;
}
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: 444, done: false}
console.log(iterator.next()); //{value: undefined, done: true}
实例2:
//生成器函数在异步任务下的表现
//异步编程 定时器(异步任务)避免回调地狱(回调中套回调)
function one() {
setTimeout(()=>{
let data = "用户数据";
//第二次调用next,当前实参会作为第一个yield语句的返回结果
iterator.next(data);
},1000)
}
function two() {
setTimeout(()=>{
let data = "订单数据";
//第三次次调用next,当前实参会作为第二个yield语句的返回结果
iterator.next(data);
},2000)
}
function three() {
setTimeout(()=>{
let data = "商品数据";
//第四次调用next,当前实参会作为第三个yield语句的返回结果
iterator.next(data);
},3000)
}
function * gen() {
let users = yield one();
console.log(users);
let orders = yield two();
console.log(orders);
let goods = yield three();
console.log(goods);
}
let iterator = gen();
//第三次次调用next
iterator.next();
Promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
实例解析
实例
//实例化Promise对象
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('good');
},1000)
});
//指定回调
const result = p.then( value => {
console.log(value); //good
//1.非 promise 类型的属性
// return 123;
//2.是 promise 对象
// return new Promise((resolve, reject) => {
// // resolve('OK');
// reject('error');
// })
//3.抛出错误
throw new Error('Error');
}, reason => {
console.log(reason);
return 321;
});
console.log(result);
//链式调用
p.then(value => {},reason => {}).then(value => {},reason => {});
解析
实例化Promise对象
new Promise()会接收一个函数类型值的参数function () {},函数类型值的参数默认为resolve和reject,通过调用resolve和reject这两个函数来改变promise对象(p)的状态,当调用resolve时,对象(p)的状态会变为成功。反之调用reject表示失败。
回调then方法
promise对象(p)还能调用then方法,then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定,且then方法参数是两个函数类型,这两个函数类型都有一个形参,成功的形参一般设为value,失败的设为reason。value对应的是上方的resolve,而reason对应的是reject。
- 如果假设对象fn的回调函数中返回的结果是非promise类型的对象,对象fn的返回结果也会是状态为成功的promise对象
异步封装读取文件
多个异步任务的情况下,代码会不断缩进,使用Promise能避免不断缩进的情况
const fs = require('fs')
// fs.readFile('let.html',(err,data)=>{
// if (err) throw err;
// console.log(data.toString());
// });
//多个异步任务的情况下,代码会不断缩进,使用Promise能避免不断缩进的情况
const p = new Promise(function (resolve, reject) {
fs.readFile('let1.html',(err,data)=>{
if (err) reject(err);
resolve(data)
})
})
p.then(function (value) {
console.log(value.toString());
},function (reason) {
console.error(reason);
})
封装AJAX请求
const p = new Promise((resolve, reject)=>{
// 创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open('GET','https://api.apiopen.top/getJoke');
//发送
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( value => {
console.log(value);
}, reason => {
console.log(reason);
});
实践练习-链式调用多个文件内容读取
//多个异步任务的情况下,代码会不断缩进,形成回调地狱,使用Promise能避免不断缩进的情况
const p = new Promise(function (resolve, reject) {
fs.readFile('let1.html',(err,data)=>{
resolve(data);
})
})
p.then(value => {
return new Promise(((resolve, reject) => {
fs.readFile('let2.html',(err,data)=>{
resolve([value,data]);
})
}));
}).then(value => {
return new Promise(((resolve, reject) => {
fs.readFile('let3.html',(err,data)=>{
value.push(data);
resolve(value);
})
}))
})
catch方法
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
reject('good');
},1000)
});
p.catch(function (reason) {
console.warn(reason);
});
集合
集合Set介绍与API方法
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯
一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进
行遍历,集合的属性和方法:
\1) size 返回集合的元素个数
\2) add 增加一个新元素,返回当前集合
\3) delete 删除元素,返回 boolean 值
\4) has 检测集合中是否包含某个元素,返回 boolean 值
\5) clear 清空集合,返回 undefined
<!-- 声明集合Set -->
let s = new Set();
let s2 = new Set(['aaa','bbb','ccc','ddd','aaa']);
//添加新元素
// s2.add('eee');
//删除元素
// s2.delete('aaa');
//检测是否存在
// console.log(s2.has('eee'));
//清空
// s2.clear();
//遍历集合
for (let v of s2){
console.log(v);
}
// console.log(s2);
集合Set实践
<!-- 声明集合Set -->
let s2 = ['aaa','bbb','ccc','ddd','aaa','eee','ccc','bbb'];
//数组去重
// let arr1 = [...new Set(s2)];
//交集
let s3 = ['bbb','eee','aaa','ccc','bbb'];
// let arr1 = [...new Set(s2)].filter(item=>{
// let arr2 = new Set(s3);
// if (arr2.has(item)){
// return true;
// }else {
// return false;
// }
// });
//代码优化
// let arr1 = [...new Set(s2)].filter(item => new Set(s3).has(item));
// console.log(arr1);
//并集
// let union = new Set([...s2,...s3]);
// console.log(union);
//
// let union1 = [...new Set([...s2,...s3])];
// console.log(union1);
//差集
let diff = [...new Set(s2)].filter(item => !new Set(s3).has(item))
console.log(diff);
Map介绍与API
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”
的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了
iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。 Map 的属
性和方法:
\1) size 返回 Map 的元素个数
\2) set 增加一个新元素,返回当前 Map
\3) get 返回键名对象的键值
\4) has 检测 Map 中是否包含某个元素,返回 boolean 值
\5) clear 清空集合,返回 undefined


Class类
ES6 提供了更接近传统语言的写法,引入了 Class(类) 这个概念,作为对
象的模板。通过 class 关键字,可以定义类。基本上, ES6 的 class 可以看作只是
一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象
原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
\1) class 声明类
\2) constructor 定义构造函数初始化
\3) extends 继承父类
\4) super 调用父级构造方法
\5) static 定义静态方法和属性
\6) 父类方法可以重写
静态成员
函数对象和实例对象的属性不相通
<!-- 函数对象和实例对象的属性不相通 -->
//函数对象
// function Phone() {
//
// }
<!-- 相当于静态属性属于函数对象 -->
// Phone.name = 'aaa';
// Phone.change = function () {
// console.log('bbb');
// }
//等同于上方代码
class Phone {
static name = 'aaa';
static change(){
console.log('bbb');
}
}
<!---->
Phone.prototype.size = '5cm';
//实例对象
let n = new Phone();
console.log(n.name);//undefined
console.log(Phone.name);//aaa
n.change();//undefined
console.log(n.size);//5cm
构造函数继承(ES5)
function Phone(brand,price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function () {
console.log("call");
}
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('ccc');
}
smartPhone.prototype.playGame = function () {
console.log('ddd');
}
const p = new smartPhone('aaa',25235,'black','5cm');
console.log(p);
Class的类继承(ES6之后)
使用super调用父类的构造函数的构造方法
class Phone{
//构造方法
static key = 'key';
constructor(brand,price,key) {
this.brand = brand;
this.price = price;
this.key = key;
}
call(){
console.log(this.brand);
}
}
class SmartPhone extends Phone{
//构造方法
constructor(brand,price,color,size,key) {
//使用super调用父类的构造函数的构造方法
super(brand,price,key);
this.color = color;
this.size = size;
//调用父类的静态属性的 方法一
// this.key = SmartPhone.key;
this.key = key;
}
photo(){
console.log('photo');
}
playGame(){
console.log('playGame');
}
}
const sp = new SmartPhone('mi',1234,'black','7cm');
//调用父类的静态属性的 方法二
console.log(SmartPhone.key);
//调用父类的静态属性的 方法一
// console.log(sp.key);
console.log(sp);
Class的getter和setter
class Phone {
get price(){
console.log('读取价格');
return 126854;
}
set price(p){
if (p<123){
console.log('small');
}else {
console.log('big');
}
}
}
let pri = new Phone();
//Get
console.log(pri.price);
//Set
pri.price = 126;
数值扩展
二进制和八进制
ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和0o 表示。
let a = 0b1010; //二进制
let b = 0o777; //八进制
let c = 100; //十进制
let d = 0xfff; //十六进制
Number.isFinite()与Number.isNaN()
Number.isFinite() 用来检查一个数值是否为有限的
Number.isNaN() 用来检查一个值是否为 NaN
console.log(Number.isFinite(Infinity)); //无穷(false) )
Number.parseInt()与Number.parseFloat()
ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变。
parseInt()字符串转整数
console.log(Number.parseInt('5164654佛覅哦')); //5164654
parseFloat()字符串转浮点数
console.log(Number.parseFloat('7.5164654佛覅哦')); //7.5164654
Number.isInteger()
Number.isInteger() 用来判断一个数值是否为整数
Math.trunc()
用于去除一个数的小数部分,返回整数部分。
console.log(Math.trunc(7.5164654)); //7
Math.sign()
判断一个数字为正数、零还是负数
1 正数
0 零
-1 负数
console.log(Math.sign(400)); //1
console.log(Math.sign(0)); //0
console.log(Math.sign(-41.1)); //-1
对象扩展
Object.is
比较两个值是否严格相等
<!-- 等同于===,除了NaN -->
console.log(Object.is(100,100)); //true
console.log(Object.is(NaN,NaN)); //true
console.log(NaN === NaN); //false
Object.assign
对象的合并,将源对象的所有可枚举属性,复制到目标对象
//以前对象config1为基准,后面对象config2中有同属性名的属性值覆盖前对象config1的
console.log(Object.assign(config1,config2));
getPrototypeOf 、 setPrototypeOf
可以直接设置对象的原型对象
const school = {
name: '清华'
};
const cities = {
diqu: ['beijing','shanghai','shenzhen']
};
Object.setPrototypeOf(school,cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
模块化
模块化的好处
模块化的优势有以下几点:
\1) 防止命名冲突
\2) 代码复用
\3) 高维护性
模块化规范产品
ES6 之前的模块化规范有:
纸面规范 应用实例
\1) CommonJS => NodeJS 、Browserify(前端代码打包)
\2) AMD => requireJS(浏览器端)
\3) CMD => seaJS(浏览器端)
ES6模块化语法
模块功能主要由两个命令构成:export 和 import。
export 命令用于规定模块的对外接口
import 命令用于输入其他模块提供的功能
模块暴露方式
分别暴露

统一暴露

默认暴露
export defalut{
//加暴露数据
}

ES6引入模块数据方式
通用引入
import * as m1 from "m1.js";
import * as m2 from "m2.js";
解构赋值形式
import {school,teach} from "./js/m1.js";
import {school as sch,findJob} from "./js/m2.js";
import {default as m3} from "./js/m3.js";
console.log(school,teach);
简便形式(针对默认暴露)
import m3 from "./js/m3.js"
console.log(m3);
浏览器使用ES6模块化数据
方法一
使用标签,在标签里写代码
<script type="module">
import {school,teach} from "./js/m1.js";
import {school as sch,findJob} from "./js/m2.js";
import {default as m3} from "./js/m3.js";
console.log(school,teach);
</script>
方法二
用标签src属性去引入文件,类型设置为module
<script src="./js/m4.js" type="module"></script>
babel对ES6模块化转换
-
语法兼容性转换
ES6 模块化使用import和export语法,而旧版 JavaScript 环境不支持这些语法。Babel 可以将它们转换为 CommonJS 模块形式(如require()和module.exports):-
ES6 代码:
javascript复制代码import add from './math.js'; export const multiply = (a, b) => a * b; -
Babel 转换后:
javascript复制代码const add = require('./math.js'); exports.multiply = (a, b) => a * b;
-
-
通过插件实现模块化转换
Babel 使用@babel/preset-env和@babel/plugin-transform-modules-commonjs等插件来处理模块语法转换,确保代码在 Node.js 和旧版浏览器中兼容。 -
Tree Shaking 支持
Babel 与现代打包工具(如 Webpack)结合时,可以保留 ES6 模块化结构,支持 Tree Shaking 优化,减少未使用代码的打包。
总结
Babel 的核心作用是确保 ES6 模块化代码能够在不支持现代模块系统的环境中正常运行,同时通过插件体系提供灵活的配置选项,以满足不同项目的需求。
使用方式
初始化npm npm init --yes
安装工具babel npm i babel-cli babel-cli babel-preset-env browserify -D
转换ES6 npx babel js -d brower-js --presets=babel-preset-env
打包 npx browserify brower-js/m4.js -o brower-js/bundle.js
ES7新特性
Array.prototype.includes
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
const shuzu = ['发呼呼','放假放','阿吉覅','哦破发键盘'];
console.log(shuzu.includes('发呼呼')); //true
console.log(shuzu.includes('发呼呼23')); //false
指数操作符
在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
console.log(2 ** 11); //2024
console.log(Math.pow(2,12)); //4096
ECMASript 8 新特性
async 和 await
async 和 await 两种语法结合可以让异步代码像同步代码一样
async 函数
-
async 函数的返回结果为 promise 对象
-
async函数的promise 对象的结果和状态由 async 函数执行的返回值决定。如果回调函数的返回结果为非Promise对象,那回调函数的返回结果为async函数的返回值,且状态为成功;回调函数的返回结果为抛出错误,async函数的返回值为回调函数的报错原因,状态为错误;回调函数的返回结果为Promise对象,返回值和状态都由这个Promise对象决定。
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 m1() {
return new Promise((resolve, reject) => {
fs.readFile('js/m1.js',(err,data)=>{
if (err) throw err;
resolve(data);
});
})
}
function m2() {
return new Promise((resolve, reject) => {
fs.readFile('js/m2.js',(err,data)=>{
if (err) throw err;
resolve(data);
});
})
}
function m3() {
return new Promise((resolve, reject) => {
fs.readFile('js/m3.js',(err,data)=>{
if (err) throw err;
resolve(data);
});
})
}
async function main() {
let mR1 = await m1();
let mR2 = await m2();
let mR3 = await m3();
console.log(mR1.toString());
}
main()
async和await结合发送ajax请求
function sAjax(url) {
return new Promise((resolve, reject) => {
//创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open('GET',url);
//发送
xhr.send();
//绑定事件
xhr.onreadystatechange = function () {
if (xhr.readyState===4){
if (xhr.status >= 200 && xhr.status < 300){
resolve(xhr.response);
}else {
reject(xhr.status);
}
}
}
});
}
async function main() {
let sajax = await sAjax('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=2');
console.log(sajax);
}
main();
Object.values 和 Object.entries
Object.values()方法
返回一个给定对象的所有可枚举属性值的数组
Object.entries()方法
返回一个给定对象自身可遍历属性 [key,value] 键值对的数组,键值对(集合对象)转化为数组,方便创建Map
const school = {
name : "清北",
cities: ['北京','上海','广州'],
kemu : ['前端','后端','Python','Java']
};
// //获取对象所有的键
// console.log(Object.keys(school));
// //获取对象所有的值
// console.log(Object.values(school));
//获取对象所有的键值对,转化为数组
console.log(Object.entries(school));
//创建Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));
Object.getOwnPropertyDescriptors()
对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(school));

通过Object.create对象时,属性描述对象的结构。
/*
* 参数1:原型对象
* 参数2:描述对象(必须是对象)
* */
const obj =Object.create(null,{
name :{
value:'清北',
//属性特性
//是否可写
writable:true,
//是否可以删除
configurable:true,
//是否可以连续
enumerable:true
}
})
console.log(Object.getOwnPropertyDescriptors(obj));
ES9新特性
扩展运算符与rest参数
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,
在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
function connect({host,type,...user}) {
console.log(host);
console.log(type);
console.log(user);
}
connect({
host:'127.0.0.1',
port:'3306',
username:'root',
password:'root',
type:'Get'
})
127.0.0.1
Get
对象合并
const skillOne = {
q:'天音波',
}
const skillTwo = {
w:'金钟罩',
}
const skillThree = {
e:'天雷破',
}
const skillFour = {
r:'猛龙摆尾',
}
const skill = {skillOne,skillTwo,skillThree,skillFour}
const skill1 = {...skillOne,...skillTwo,...skillThree,...skillFour}
console.log(skill);
console.log(skill1);

正则扩展
命名捕获分组
ES9 允许命名捕获组使用符号『?
let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
// const reg = /<a href="(.*)">(.*)<\/a>/;
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
// console.log(result[1]);
// console.log(result[2]);
console.log(result.groups.url);
console.log(result.groups.text);
正向和反向断言
ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。
let str = 'JS5211314 你知道么 555 啦啦啦';
//正向断言
const reg1 = /\d+(?=\s*啦)/; //\s*允许空格出现0次或多次
const result1 = reg1.exec(str);
console.log(result1);
// //反向断言
// const reg2 = /(?<=么)\d+/;
// const result2 = reg2.exec(str);
// console.log(result2);
dotAll模式
正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行
终止符出现
let str = `
<ul>
<li>
<a>三国演义</a>
<p>上映日期:1946年6月13日</p>
</li>
<li>
<a>水浒传</a>
<p>上映时间:2089年8月21日</p>
</li>
</ul>
`;
// const reg = /<li>\s+<a>(?<title>.*?)<\/a>\s+<p>(?<date>.*?)<\/p>.*?<\/li>/;
const reg = /<li>.*?<a>(?<title>.*?)<\/a>.*?<p>(?<date>.*?)<\/p>.*?<\/li>/gs; //g 标志表示全局匹配全部符合要求的,s 标志使 . 能够匹配换行符
//获取值方法一: 多次使用.exec()
// reg.exec(str)是单次调用匹配 的方法。当正则表达式包含全局标志 g 时,exec 会在每次调用后记录它的匹配位置,下次调用从该位置继续。由于你只调用了一次 exec,它仅匹配到第一条数据。
// const result1 = reg.exec(str);
// const result2 = reg.exec(str);
// console.log(result1);
// console.log(result2);
//获取值方法二: while循环来多次使用.exec()
// let result;
// const data = [];
// //持续判断result值是否存在,存在就输出,否则退出循环
// while (result = reg.exec(str)){
// data.push({title:result.groups.title,date:result.groups.date})
// }
// console.log(data);
//获取值方法三: matchAll
const result = str.matchAll(reg);
for (const resultKey of result) {
console.log(resultKey.groups.title);
console.log(resultKey.groups.date);
}
ES10新特性
Object.fromEntries
Object.fromEntries和Object.entries是一对互逆运算。
Object.fromEntries()方法将键值对数组转换为对象。
Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组。
//键值对转化为数组
const school = {
name : "清北",
cities: ['北京','上海','广州'],
kemu : ['前端','后端','Python','Java']
};
console.log(Object.entries(school)); //输出:[Array(2), Array(2), Array(2)]
//数组转化为键值对
const entries = [['x', 1], ['y', 2]];
const obj = Object.fromEntries(entries);
console.log(obj); //输出:{x: 1, y: 2}
trimStart和trimEnd
et str = ' I Love You ';
console.log(str.trim()); //清除全部空格
console.log(str.trimStart()); //清除左边的全部空格,和trimLeft()有相同效果
console.log(str.trimEnd()); //清除右边的全部空格,和trimRight()有相同效果
Array.prototype.flat与flatMap
Array.prototype.flat
//将多维数组转化为低维数组
const arr = [1,2,3,4,[5,6,[7,8,9]]];
//参数为深度,默认是1
console.log(arr.flat(1)); //输出为:[1, 2, 3, 4, 5, 6, [7, 8, 9]]
console.log(arr.flat(2)); //输出为:[1, 2, 3, 4, 5, 6, 7, 8, 9]
flatMap
const words = ["hello world", "flatMap is great"];
const result = words.flatMap(sentence => sentence.split(" "));
console.log(result);
// ["hello", "world", "flatMap", "is", "great"]
经验
const arr = [1, 2, 3, 4, [5, 6, 7, 8, 9]];
// console.log(arr.flatMap(item => [item * 10])); //输出为:[10, 20, 30, 40, NaN]
//item 为数组 [5, 6, 7, 8, 9],执行 [5, 6, 7, 8, 9] * 10 返回 NaN,因为数组不能直接用于乘法运算。
const flattened = arr.flat().map(item => item * 10); //flat()默认参数为1
console.log(flattened); // [10, 20, 30, 40, 50, 60, 70, 80, 90]
Symbol.prototype.description
let s = Symbol('烧过水的');
console.log(s.description); //烧过水的
ECMASript 11新特性
String.prototype.matchAll
let str = `
<ul>
<li>
<a>三国演义</a>
<p>上映日期:1946年6月13日</p>
</li>
<li>
<a>水浒传</a>
<p>上映时间:2089年8月21日</p>
</li>
</ul>
`;
const reg = /<li>.*?<a>(?<title>.*?)<\/a>.*?<p>(?<date>.*?)<\/p>.*?<\/li>/gs; //g 标志表示全局匹配全部符合要求的,s 标志使 . 能够匹配换行符
const results = [...str.matchAll(reg)];
const resultSet = results.map(result => ({
title: result.groups.title,
date: result.groups.date
}));
console.log(resultSet);
类的私有属性
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);
Promise.allSettled和Promise.all
都是用来处理批量异步任务的场景
//创建两个Promise对象
const p1 = new Promise((resolve, reject) => {
setTimeout(()=>{
reject('商品1');
});
});
const p2 = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('商品2');
});
});
//批量执行异步任务
//当需要每个异步任务都能执行并得到结果就使用allSettled
const allset = Promise.allSettled([p1,p2]);
console.log(allset);
//当需要每个异步任务都能成功再往下执行,就使用all
const all = Promise.all([p1,p2]);
console.log(all);
可选链操作符
//可选链操作符 ?.
function main(config) {
//数据属性是否传入判断
// const dbHost = config && config.db && config.db.host;
const dbHost = config?.db?.host;
console.log(dbHost);
}
main({
db:{
host:'192.168.2.1',
username:'root'
},
cache:{
host:'192.168.2.3',
username:'cache'
}
})
动态import导入
按需加载(懒加载)
<body>
<button id="btn">check</button>
</body>
<script src="./动态import.js" type="module"></script>
//正常情况下导入
// import * as hell from "./动态import-hello.js";
const btn = document.getElementById('btn');
btn.onclick = function () {
//import()导入结果是一个Promise对象
import('./动态import-hello.js').then(module =>{
module.hello();
})
}
export function hello() {
alert('Hello')
}
BigInt类型
// //大整型
// let n = 521n;
// console.log(n,typeof(n)); //521n 'bigint'
//函数
// let n = 123;
// console.log(BigInt(n)); //123n
// console.log(BigInt(1.2)); // The number 1.2 cannot be converted to a BigInt because it is not an integer
//大数值运算
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
globalThis对象
globalThis 是 ECMAScript 2020(ES11)引入的一个全局对象,用于在不同环境中访问全局作用域(全局对象),它提供了一个统一的方式来获取全局作用域,无论是在浏览器、Node.js 还是 Web Workers 等环境中。
为什么需要 globalThis
在不同的执行环境中,全局对象的名称不一致:
- 浏览器:
window - Node.js:
global - Web Workers:
self
globalThis 统一了这些差异,确保代码在不同的环境中都能访问到全局对象,不需要依赖特定的名称。

浙公网安备 33010602011771号