ECMAScript 6-11
第一章 ES6 新特性
1.1 let 关键词
let关键词用来声明对象,其特点如下
- 不允许重复声明
- 存在块级作用域
- 不存在变量提升
- 不影响作用域链
代码演示:
//1.变量不能重复声明
let star = "saber";
//let star = "alterSaber";//报错
//3.存在块级作用域
{
let girl = "saber";
var man = "jojo";
}
console.log(man);
//console.log(girl);
//5.不影响块级作用域
{
let school = "尚硅谷";
function fn(){
console.log(school);
}
fn();
}
1.2 const 关键词
const 关键词用来声明常量,const声明有以下特点
- 声明必须赋值
- 标识符一般大写(规范)
- 不允许重复声明
- 其值不允许修改
- 存在块级作用域
注意: 对象属性修改和数组元素变化不会出发 const 错误 应用场景:声明对象类型使用 const,非对象类型声明选择 let
1.3 解构赋值
演示代码如下:
//1.数组的解构
const F4 = ['saber','lancer','archer','caster'];
let [s,l,a,c] = F4;
console.log(s,l,c,a);
//2.对象的解构
const stand = {
name:'白金之星',
master:'承太郎',
age:'19',
methods:function() {
for (let i = 0; i < 11; i++) {
console.log('欧拉!');
console.log(this.name);//这个函数解构后this是会变成window的 注意
}
},
}
let {name,age,master,methods} = stand;
console.log(name);
console.log(master);
methods();
console.log(stand.name);
stand.methods();
const F4 = ['saber','lancer','archer','caster'];
let [s,l,a,c] = F4;
console.log(s,l,c,a);
输出结果如下:
1.4 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
- 可以使用 ${xxx} 形式输出变量
代码如下:
//1.内容中可以出现换行符
let str = `我是。。。。
四年级学生森下下士
我是你们的 老大哥!`;
console.log(str);
//2.可以进行变量的拼接
let name = "saber";
let me = `${name}是我最喜欢的角色`;
console.log(me);
1.5 简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
代码演示:
let name = "尚硅谷";
let change = function(){
console.log('牛逼');
}
const school = {
name,
change,
add(){
console.log('哈哈哈哈!');
}
}
console.log(school);
1.6 函数参数的默认值
代码如下:
//形参的初始值,一般要把这种有默认值的形参放在参数列表的最后
function add(a=3,b=6){
return a+b;
}
console.log(add(1,2));
console.log(add());
//可以与解构赋值相结合
function connect({host,username,password,port=3366}){
console.log(host,username,password,port);
}
connect({
host:'localhost',
username:'root',
password:'123456',
/* port:2233, */
})
1.7 rest 参数
ES5用arguments来获取函数实参,但是返回的是一个伪数组(对象)
ES6用rest参数来代替arguments
//rest 参数
function _date(...args){
console.log(args);//这里返回的就是数组了
}
_date('aaa','bbb','ccc');
//rest 参数必须要放到最后
function args(a,b,...args){
console.log(a,b,args);
}
args(1,2,3,4,5,6);
1.8 spread 扩展运算符
... 扩展运算符能将数组转换为逗号分隔的参数序列
代码如下:
const stand = ['白金之星','绿色法皇','银色战车'];
function arr(){
console.log(arguments);
}
arr(stand);
arr(...stand);
运行结果如下:
练习
<body>
<div></div>
<div></div>
<div></div>
<script>
//数组的合并
const arr1 = ['saber','jojo','alen'];
const arr2 = ['尼禄','dio','阿强'];
const arr3 = [...arr1,...arr2];
console.log(arr3);
//数组的克隆,如果里边有引用数据类型的话这克隆就是一个浅拷贝
const oldarr = [1,2,3,'jojo'];
const newarr = [...oldarr];
console.log(newarr);
//将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
console.log(divs);//这里其实是个对象
const divarr = [...divs];
console.log(divarr);//这里输出的就是真正的数组了
</script>
</body>
运行结果如下:
1.9 Symbol简介
1.9.1 Symbol的基本使用
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点:
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用 for…in 循 环遍 历 ,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
//创建Symbol
let s = Symbol();
console.log(s,typeof s);
let s2 = Symbol('尚硅谷');
let s3 = Symbol('尚硅谷');
console.log(s2 === s3);
//通过Symbol.for创建
let s4 = Symbol.for('saber');
let s5 = Symbol.for('saber');
console.log(s4 === s5);
//当然该数据类型不能和数据进行运算
console.log(s2,s3,s5,s4);
遇到唯一性的场景时要想到 Symbol
1.9.2 Symbol创建对象属性
代码如下:
//添加方式一
//向对象中添加up down 方法,前提是不知道里面有有没有该同名方法了
let game = {
name: '给她爱5',
up(){
console.log('上划')
},
down(){
console.log('下滑');
}
}
//声明一个方法
let methods = {
up:Symbol(),
down:Symbol()
};
game[methods.up] = function(){
console.log('我奥上划');
}
game[methods.down] = function(){
console.log('我要下滑');
}
console.log(game);
//方式二
let youxi = {
name:'狼人杀',
//添加独一无二的方法
[Symbol('say')]:function(){
console.log('说话');
}
}
console.log(youxi);
运行结果如下:
1.9.2 Symbol内置的值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值, 指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景自动执行。
代码如下:
class Person{
//作用就是可以自己控制类型的检测
static [Symbol.hasInstance](param){
console.log(param);//该参数为instanceof前面的对象
console.log('我被用来检测类型了')
//return true;
}
constructor(){
}
}
let o = {
test:'测试'
};
let _o = new Person();
//比如,foo instanceof Foo在语言内部,实际调用的是Foo[Symbol.hasInstance](foo)。
console.log(o instanceof Person);
console.log(_o instanceof Person);//false 因为修改了静态方法。_o本身就是MyClass的实例,如果注释了静态方法就会返回true。
const arr = [1,2,3];
const arr2 = [2,3,4];
arr2[Symbol.isConcatSpreadable] = false;//表示合并数组不展开
console.log(arr.concat(arr2));
运行结果:
1.10 迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6有一种新的遍历命令 for...of 循环,原生具有iterator的就可以使用该命令遍历
如:
Array
Arguments
Set
Map
String
TypedArray
NodeList
迭代器工作原理:
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
演示代码如下:
//声明一个数组
const xiyou = ['saber','lancer','jojo'];
for(let item of xiyou){
console.log(item);
}
//先获取迭代器属性
let iterator = xiyou[Symbol.iterator]();
console.log(iterator);
console.log(iterator.next());//没每调用一次就像后迭代一次,内部是指针操纵移动
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
运行结果:
迭代器实例实例:
//声明一个对象
const banji = {
name: '一班',
stus: [
'saber',
'jojo',
'knight'
],
stus1: [
'sabers',
'jojos',
'knights'
],
//自定义添加迭代器接口属性
[Symbol.iterator]() {
let index = 0;//索引变量
return {
next: () => {
if (index < this.stus1.length) {
const result = {
value: this.stus1[index],
done: false,
}
index++;//下标自增
return result;//返回结果
}
else {
return {
value: undefined,
done: true,
}
}
}
}
}
}
//遍历这个对象,需求返回其中数组中的成员
for (let item of banji) {
console.log(item)//(在没有自定义迭代器时)会报错
}
let iterator = banji[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
运行结果:
1.11 生成器
生成器是es6为解决异步编程提供的解决方案
//简介,异步编程的一个解决方案
function * gen(){
//console.log('hello generator');
yield '一直没有耳朵';//这个yield可以看作函数内部的分隔符
//console.log('111')
yield '一直没有眼睛';
//console.log('222')
yield '一直没有尾巴';
//console.log('333')
yield '真奇怪';
//console.log('444')
}
let iterator = gen();//通过next()代码进行一步一步的执行
/* iterator.next();//还必须调用next()方法才能调用
iterator.next();
iterator.next();
iterator.next();
iterator.next(); */
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//当然还是可以对函数进行遍历
for(let item of gen()){
console.log(item);
}
运行结果:
代码说明:
- “ * ” 的位置没有限制
- 生成器的返回结果是迭代器对象,调用迭代器对象的next方法可以得到yield语句的值
- yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
- next 方法可以传递实参,作为 yield 语句的返回值
1.11.1 生成器的参数传递
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'));//第二个next传入的参数将会作为第一个yield语句的返回结果
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
运行结果:
生成器实例
//现在有三个任务,一秒执行第一个,再过两秒执行第二个,再过三秒执行第三个
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);//第二次调用其中的参数会作为第一个yield的语句的返回值
}, 1000);
}
function getOrders() {
setTimeout(() => {
let data = "订单数据"
_iterator.next(data);
}, 1000);
}
function getGoods() {
setTimeout(() => {
let data = "商品数据"
_iterator.next(data);
}, 1000);
}
//声明生成器函数
function * _gen(arg){
console.log(arg)
let user = yield getUSers(arg);
console.log(user);
let order = yield getOrders();
console.log(order)
let goods = yield getGoods();
console.log(goods)
}
let _iterator = _gen("000");
_iterator.next();
运行结果:
1.12 Set(集合)
ES6提供的新的数据结构,它类似于数组,但成员的值都是唯 一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进 行遍历。集合的属性和方法:
- size 返回集合中的元素
- add 增加元素
- delete 删除元素,返回当前集合
- has 检测集合中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
//声明一个set
let s = new Set();
let s2 = new Set([1,2,3,4,1,1]);//会自动去重
console.log(s2)
console.log(s2.size);//输出长度
//添加新的元素
s2.add('nmsl');//push
console.log(s2);
//删除
s2.delete('nmsl');
console.log(s2);
//检测
console.log(s2.has('nmsl'));
console.log(s2.has(1));
//清空
/* s2.clear();
console.log(s2); */
//遍历
for(let item of s2){
console.log(item)
}
运行结果:
实例
let arr = [1, 2, 2, 2, 2, 3, 3, 3, 4,6, 4, 4, 1, 5, 5, 67, 8, 9];
let arr2 = [1, 3, 5, 7, 4, 9, 5,6];
//数组去重
/* let result = [...new Set(arr)];
console.log(result); */
//交集
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item))
console.log(result);
//并集(合并去重)
let result2 = [...new Set([...arr,...arr2])];
console.log(result2)
//差集(交集的逆运算)
let result3 = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
let result4 = [...new Set(arr2)].filter(item => !(new Set(arr).has(item)));
console.log([...result3,...result4])
运行结果:
1.13 Map
Map也是ES6提供的一种新的数据结构,是键值对的集合。Map 也实现了 iterator 接口。
Map 的属性和方法:
- size 返回 Map 的元素个数
- set 增加一个新元素,返回当前 Map
- get 返回键名对象的键值
- has 检测 Map 中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
//声明Map
let m = new Map();
m.set('name','zhangheng');
m.set('change',function(){
console.log("我们可以改变你!");
})
let key = {
school:'swust',
};
m.set(key,['北京','上海','深圳']);
console.log(m.size);
console.log(m);
//删除
//m.delete('name');
console.log(m);
//获取(通过key获取value)
console.log(m.get('change'));
//清空
m.clear();
//当然也可进行for of运算
运行结果:
1.14 class简介
ES6新的构建对象的方法
ES5实例化对象的方法:
//es5的实例化对象方法
function Phone(brand,price){
this.brand = brand;
this.price = price;
}
///添加方法
Phone.prototype.call = function(){
console.log('我可以打电话!');
}
let huawei = new Phone('华为',1999);
huawei.call();
console.log(huawei);
ES6实例化对象的方法:
//es6实例化对象方法
class Person{
//构造方法
constructor(name,age){
this.name = name;
this.age = age;
}
//添加方法
eat(){
console.log('我可以吃饭');
}
}
let one = new Person('zhangheng',21);
console.log(one);
one.eat();
运行结果:
1.14.1 class的静态成员
function Phone(){
}
Phone.nick = "shouji";
Phone.change = function () {
console.log('change you!');
}
console.log(Phone);
Phone.change();
console.log(Phone.nick);
let nokia = new Phone();
console.log(nokia,nokia.nick);
//nokia.change();//error
/* 实例对象和函数对象是不通的 */
class Person{
//静态属性
static name = '人';
static eat(){
console.log('我可以吃饭');
}
}
let one = new Person();
console.log(one.name);
/* 静态属性是属于类的而不属于实例化对象 */
运行结果:
1.14.2 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('原神,启动');
}
//对父类方法进行重写
call(){
//注意在js语法中子类是不可以直接调用父类的同名方法的 super()也是不能出现的
console.log('我可以视频通话');
}
}
let xiaomi = new SmartPhone('小米',2999,'黑色','4,97inch');
console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
运行结果:
1.14.3 get和set
//get和set
class Phone{
get price(){
console.log('价格属性被读取了');
return 'wryyyyy';
}
set price(newValue){
console.log('价格改变了');
}
}
//实例化对象
let s = new Phone();
//只要读取了这个属性就会执行对应函数
s.price
//返回值也一样
console.log(s.price);
//传入新值就会调用对应函数
s.price = 'free';
运行结果:
1.15 数值扩展
//Number.EPSILON 是js表示的最小精度
console.log(Number.EPSILON);
/* 在js中两个数的差的绝对值小于了这个精度就认为两数相等,通常用于浮点数运算*/
console.log(0.1 + 0.2 === 0.3);
//这就可以用这个最小精度来解决
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));
//二 八 十六进制表示
let b = 0b1010;
let o = 0o777;
let x = 0xff;
console.log(b,o,x);
//Number.isFinite() 检测一个数值是否为有限数
//Number.isNaN() 用来检查一个值是否为 NaN
//Math.trunc 用于去除一个数的小数部分,返回整数部分。
//Number.isInteger() 用来判断一个数值是否为整数
运行结果:
1.16 对象扩展
//Object.is 判断两个值是否相等
console.log(Object.is(NaN,NaN));
console.log(NaN === NaN);
//Object.assign 对象的合并
const obj = {
name:'zhangheng',
age:13,
savent:'saber'
}
const obj2 = {
name:'topzhang',
age:23,
stand:'白金之星',
}
console.log(Object.assign(obj,obj2));//在obj基础上进行改变
/* 出现同名属性后者会覆盖前者 */
//Object.setPrototypeOf Object.getPrototypeOf 设置原型对象
Object.setPrototypeOf(obj,obj2);
console.log(obj);
console.log(Object.getPrototypeOf(obj))//获取原型 obj2
运行结果:
1.17 ES6的模块化
1.17.1 导出的js实例文件
//m1.js
export let school = "m1-swust";
export function teach() {
console.log('m1我是老师')
}
//m2.js
//统一暴露
let school = "m2-swust";
function _teach() {
console.log('m2我是老师')
}
export {school,_teach};
//m3.js
//默认暴露(只能存在一个默认导出)
export default {
school:'m3-swust',
teach(){
console.log('m3老师')
}
}
//app.js
//入口文件
import * as m1 from './m1.js'
import * as m2 from './m2.js'
import * as m3 from './m3.js'
console.log(m1);
console.log(m2);
console.log(m3);
//修改背景颜色
import $ from 'jquery';
$('body').css('background','red');
1.17.2 通用的导入方式
// * 表示将所有的内容全部导出为一个对象
import * as m1 from './31-模块化演示/src/js/m1.js'
import * as m2 from './31-模块化演示/src/js/m2.js'
import * as m3 from './31-模块化演示/src/js/m3.js'
console.log(m1);
console.log(m2);
console.log(m3.default);
m3.default.teach();
1.17.3 解构赋值的方式
import { school, teach } from './31-模块化演示/src/js/m1.js'
import { school as sch, _teach } from './31-模块化演示/src/js/m2.js'//这里schol与第一个js包中的重名要使用别名
//import {default as m3} from './31-模块化演示/src/js/m3.js'
import m3 from './31-模块化演示/src/js/m3.js'//就是上句的简写,只针对默认暴露
console.log(school);
console.log(sch);
_teach();
console.log(m3)
m3.teach();
console.log("-------------------------")
运行结果:
1.17.4 通过入口文件app.js统一导入
<script src="./31-模块化演示/src/js/app.js" type="module"></script>
1.17.5 通过babel进行简单打包导入演示
首先创建的目录结构如下:
注意这个目录是完成打包后的文件目录,最开始dist文件夹时空的,也没有node组件和json文件
安装工具
npm i babel-cli babel-preset-env browserify(webpack) -D
转换语法(转es5)
npx babel src/js -d dist/js --presets=babel-preset-env
//这样就在js文件夹下生成转换后的代码了
打包
npx browserify dist/js/app.js -o dist/bundle.js
最后引入打包文件
<script src="./dist/bundle.js"></script>
第二章 ES7新特性
2.1 Array.prototype.includes和幂运算
//includes
const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
/* 之前用indexOf可以检查是否存在但返回的是数字,不直观,而includes返回是布尔值 */
console.log(mingzhu.includes('西游记'));
console.log(mingzhu.includes('金瓶梅'));
// ** 幂运算 2的10次方
console.log(2 ** 10);
运行结果:
第三章 ES8 新特性
3.1 Object扩展方法
//声明对象
const school = {
name:'尚硅谷',
cities:['尚硅谷','shanghai']
}
//获取所有对象的键
console.log(Object.keys(school));
//获取值
console.log(Object.values(school));
//获取键值,方便创建map
console.log(Object.entries(school));
//对象属性的描述对象(该方法返回指定对象所有自身属性的描述对象)
console.log(Object.getOwnPropertyDescriptors(school))
运行结果:
第四章 ES9新特性
4.1 Rest/Spread 属性
/* 新增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 yasuo = {
name:'yasuo',
q:'钢斩闪',
e:'踏前闪'
}
const k = {
_name: 'yasuo',
_q: '钢斩闪',
_e: '踏前闪'
}
const m = {
...yasuo,
...k
}
console.log(m);
运行结果:
4.2 正则的命名分组
let a = '888<a href="http://www.baidu.com">string</a>';
//提取url和标签文本
const reg = /<a href="(.*)">(.*)<\/a>/;
const res = reg.exec(a);
console.log(res);
//方便了某些属性的提取
const reg1 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
console.log(reg1.exec(a))
运行结果:
4.3 正则断言
根据目标内容前后内容进行识别
//声明字符串
let str = 'JS5211314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
运行结果:
4.4 正则dotAll模式
s 开启该模式
//dot . 元字符 除换行符以外的任意单个字符
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;
//执行匹配
// const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);
运行结果:
第五章 ES10新特性
5.1 二维数组转为对象
const res = Object.fromEntries([
['name','尚硅谷'],
['xueke','java,js'],
['haha']
]);
//与entries相比一个是对象转换为二维数组,一个就是其逆运算
console.log(res);
运行结果:
5.2 数组扩展方法
//flat 平
//将多维数组转化为低位数组
const arr = [1,2,3,4,5,[6,7,8]];
console.log(arr.flat());
const arr2 = [1, 2, 3, 4, 5, [6, 7, 8,[9,10]]];
console.log(arr2.flat(2));//其中数字表示深度
//flatMap(相当于flat和map的结合使用)
// trim
let str = ' iloveyou ';
//去除前后空格
console.log(str);
console.log(str.trimStart());
console.log(str.trimEnd());
运行结果:
第六章 ES11 新特性
6.1 私有属性
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);
console.log(girl);
girl.intro();
运行结果:
6.2 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>/sg
//调用方法
const result = str.matchAll(reg);
// for(let v of result){
// console.log(v);
// }
const arr = [...result];
console.log(arr);
运行结果:
6.3 可选链操作符
// ?. 读取对象路径时当存在对象为空的时候不会继续下去从而解决报错问题
function main(config) {
// const dbHost = config && config.db && config.db.host;
const dbHost_ = config?.db?.host;
console.log(dbHost_);
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'
}
})
运行结果:
6.4 BigInt
//大整形
// 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))
运行结果:
6.5 globalThis
在以前,从不同的 JavaScript 环境中获取全局对象需要不同的语句。在 Web 中,可以通过 window
、self
或者 frames
取到全局对象,但是在 Web Workers 中,只有 self
可以。在 Node.js 中,它们都无法获取,必须使用 global
。
在松散模式下,可以在函数中返回 this
来获取全局对象,但是在严格模式和模块环境下,this
会返回 undefined
。 You can also use Function('return this')()
, but environments that disable eval()
, like CSP in browsers, prevent use of Function
in this way.
globalThis
提供了一个标准的方式来获取不同环境下的全局 this
对象(也就是全局对象自身)。不像 window
或者 self
这些属性,它确保可以在有无窗口的各种环境下正常工作。所以,你可以安心的使用 globalThis
,不必担心它的运行环境。为便于记忆,你只需要记住,全局作用域中的 this
就是 globalThis
。