ECMAScript 6-11

ECMAScript 6-11

介绍

ES(ECMAScript)是由ECMA国际通过ECMA-262标准化的脚本程序设计语言。

简单来说就是ECMAScript规范JavaScript实现了这个规范

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994年后该组织改名为ECMA国际

ECMA国际制定了许多标准,而ECMA-262只是其中的一个,所有标准列表

ECMA-262(ECMAScript)历史版本查看

ECMASript6新特性

简称ES6

新特性的目的是为了简化编码

let关键字

let关键字用来声明变量,使用let声明的变量有几个特点

  • 不允许重复声明
  • 块儿级作用域
  • 不存在变量提升
  • 不影响作用域链

应用场景:以后声明变量使用let就对了

个人感觉这个就跟其它语言一样了

const关键字

const关键字用来声明常量const声明有以下特点

  • 声明必须赋初始值
  • 标识符一般为大写(一种约定,不会出现语法错误)
  • 不允许重复声明
  • 值不允许修改
  • 块儿级作用域

注意: 对象属性修改和数组元素变化不会触发const错误

应用场景:声明对象类型使用const非对象类型声明选择let

解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值

//数组的解构赋值
const arr = ['张学友', '刘德华', '黎明', '郭富城']
let [zhang, liu, li, guo] = arr

//对象的解构赋值
const lin = {
 name: '林志颖',
 tags: ['车手', '歌手', '小旋风', '演员']
}
let {name, tags} = lin


//复杂解构
let wangfei = {
 name: '王菲',
 age: 18,
 songs: ['红豆', '流年', '暧昧', '传奇'],
 history: [
    {name: '窦唯'},
    {name: '李亚鹏'},
    {name: '谢霆锋'}
 ]
}
let {songs: [one, two, three], history: [first, second, third]} = wangfei

console.log(one, two, three, first, second, third)

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式。这样使用起来就更加方便了

函数参数与解构赋值结合ECMASript9新特性

// 定义函数
function connect({host="127.0.0.1", username, password, port}){
// ...
}

// 调用函数
connect({
    host:'mysql.com',
    username:'root',
    password:'root',
    port:3306
})

模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点

  • 字符串中可以出现换行符
  • 可以使用 ${xxx} 形式输出变量
// 定义字符串
let str = `<ul>
 <li>沈腾</li>
 <li>玛丽</li>
 <li>魏翔</li>
 <li>艾伦</li>
 </ul>`

// 变量拼接
let star = '王宁'
let result = `${star}在前几年离开了开心麻花`

当遇到字符串与变量拼接的情况使用模板字符串更方便

简化对象写法

ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁

let name = '张三'
let slogon = '永远追求行业更高标准'
let improve = function () {
 console.log('可以提高你的技能')
}

//属性和方法简写
let atguigu = {
 name,
 slogon,
 improve,
 change() {
    console.log('可以改变你')
 }
}

对象简写形式简化了代码,所以以后用简写就对了(这看起来跟其它语言类似了)

箭头函数

ES6允许使用「箭头」=>定义函数

// 通用写法
let fn = (arg1, arg2, arg3) => {
    return arg1 + arg2 + arg3;
}

箭头函数的特点跟其它语言lambda表达式类似

箭头函数的注意点:

  • 如果形参只有一个,则小括号可以省略
  • 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
  • 箭头函数this指向声明时所在作用域下this的值
  • 箭头函数不能作为构造函数实例化
  • 不能使用arguments
// 省略小括号的情况
let fn2 = num => {
    return num * 10
}

// 省略花括号的情况
let fn3 = num => num * 20

// this 指向声明时所在作用域中 this 的值
let fn4 = () => {
    console.log(this)
}

let school = {
 name: 'my school',
 getName(){
     let fn5 = () => {
        console.log(this)
     }
     fn5()
 }
}

注意:箭头函数不会更改this指向,用来指定回调函数会非常合适

函数参数默认值

// 给函数的两个参数赋初始值,如果没传递这个参数则使用默认值
// 其它很多语言都有这个特性
function add(num1=0, num2=0){
    return num1 + num2
}

注意:一般把有默认值的参数放到后面

rest参数(可变参数)

ES6引入rest参数,用于获取函数的实参,用来代替arguments。跟其它语言的可变参数一样

// 作用与 arguments 类似
function add(...args){
    console.log(args);
}
add(1,2,3,4,5);

// rest 参数必须是最后一个形参
function minus(a,b,...args){
    console.log(a,b,args);
}
minus(100,1,2,3,4,5,19)

注意:rest参数非常适合不定个数参数函数的场景

spread(扩展运算符)

扩展运算符(spread)也是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包

let tfboys = ['德玛西亚之力','德玛西亚之翼','德玛西亚皇子']
function fn(){
    console.log(arguments)
}
// 展开数组
fn(...tfboys)


// 展开对象 ECMASript9新特性
let skillOne = {
 q: '致命打击',
}
let skillTwo = {
 w: '勇气'
}
let skillThree = {
 e: '审判'
}
let skillFour = {
 r: '德玛西亚正义'
}
let gailun = {...skillOne, ...skillTwo,...skillThree,...skillFour}
// 最终会将所有对象的属性合并到一起,如下效果
let skill = {
 q: '致命打击',
 w: '勇气',
 e: '审判',
 r: '德玛西亚正义'
}

Symbol

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。

  • Symbol的值是唯一的,用来解决命名冲突的问题
  • Symbol值不能与其他数据进行运算
  • Symbol定义的对象属性不能使用for…in循环遍历 ,但是可以使用Reflect.ownKeys来获取对象的所有键名
//创建 Symbol
let s1 = Symbol()
console.log(s1, typeof s1) // Symbol() symbol

//添加标识的 Symbol
let s2 = Symbol('testSymbol')
let s2_2 = Symbol('testSymbol')
console.log(s2 === s2_2) // false

//使用 Symbol for 定义
let s3 = Symbol.for('testSymbol')
let s3_2 = Symbol.for('testSymbol') 
console.log(s3 === s3_2) // true

遇到唯一性的场景时要想到Symbol

Symbol内置值

除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。

Symbol内置值 使用场景
Symbol.hasInstance 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
Symbol.isConcatSpreadable 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开
Symbol.species 创建衍生对象时,会使用该属性
Symbol.match 当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值
Symbol.replace 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值
Symbol.search 当该对象被str.search(myObject)方法调用时,会返回该方法的返回值
Symbol.split 当该对象被str.split(myObject)方法调用时,会返回该方法的返回值
Symbol.iterator 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器
Symbol.toPrimitive 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值
Symbol. toStringTag 在该对象上面调用toString方法时,返回该方法的返回值
Symbol. unscopables 该对象指定了使用with关键字时,哪些属性会被 with环境排除
// Symbol.hasInstance 使用示例
class Person{
    static [Symbol.hasInstance](param){
        console.log(param);
        console.log("我被用来检测类型了");
        return false;
    }
}

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));

迭代器

遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作

  • ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
  • 原生具备Iterator接口的数据(可用for of遍历)
    1. Array
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypedArray
    7. NodeList
  • 工作原理
    1. 创建一个指针对象,指向当前数据结构的起始位置
    2. 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
    3. 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
    4. 每调用next方法返回一个包含valuedone属性的对象
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧']

// 获取其迭代器
let iterator = xiyou[Symbol.iterator]()

//调用对象的next方法
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())


//声明一个对象
const banji = {
    name: "终极一班",
    stus: [
        'xiaoming',
        'xiaoning',
        'xiaotian',
        'knight'
    ],
    [Symbol.iterator]() {
        //索引变量
        let index = 0
        return {
            next: ()=> {
                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提供的一种异步编程解决方案,语法行为与传统函数完全不同

function * gen(){
    // console.log(111);
    yield '一只没有耳朵';
    // console.log(222);
    yield '一只没有尾部';
    // console.log(333);
    yield '真奇怪';
    // console.log(444);
}

let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

//遍历
// for(let v of gen()){
//     console.log(v);
// }

代码说明:

  • *的位置没有限制
  • 生成器函数返回的结果是迭代器对象,调用迭代器对象的next方法可以得到yield语句后的值
  • yield相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次next方法,执行一段代码
  • next方法可以传递实参,作为yield语句的返回值
// 使用参数示例
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'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));

//模拟获取  用户数据  订单数据  商品数据 
function getUsers(data){
    setTimeout(()=>{
        let data = '用户数据';
        //调用 next 方法, 并且将数据传入
        iterator.next(data);
    }, 1000);
}

function getOrders(){
    setTimeout(()=>{
        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();
    let goods = yield getGoods();
}

//调用生成器函数
let iterator = gen();
iterator.next();

Promise

参考 Promise

Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

  • Promise构造函数:Promise (excutor) {}
  • Promise.prototype.then方法
  • Promise.prototype.catch方法

基本用法:

//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
    setTimeout(function(){
        //
        // let data = '数据库中的用户数据';
        // resolve
        // resolve(data);
        let err = '数据读取失败';
        reject(err);
    }, 1000);
});

//调用 promise 对象的 then 方法
p.then(function(value){
    console.log(value);
}, function(reason){
    console.error(reason);
})

调用then方法then方法的返回结果是Promise对象, 对象状态由回调函数的执行结果决定,如果回调函数中返回的结果是非Promise对象, 状态为成功, 返回值为对象的成功的值

Set

ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:

  • size 返回集合的元素个数
  • add 增加一个新元素,返回当前集合
  • delete 删除元素,返回boolean
  • has 检测集合中是否包含某个元素,返回boolean
  • clear 清空集合,返回undefined
//创建一个空集合
let s = new Set();

//创建一个非空集合
let s1 = new Set([1,2,3,1,2,3]);
//集合属性与方法
//返回集合的元素个数
console.log(s1.size);
//添加新元素
console.log(s1.add(4));
//删除元素
console.log(s1.delete(1));
//检测是否存在某个值
console.log(s1.has(2));
//清空集合
console.log(s1.clear());

// 数组去重
let arr = [1,3,2,3,4,6,4,1,6,7,3,4,5,6,1]
let result = [...new Set(arr)]
console.log(result)

// 交集
let arr1 = [1,3,2,3,4,6,1]
let arr2 = [12,3,14,6,1,8,9]
let set2 = new Set(arr2)
let result = [...new Set(arr1)].filter(item=> set2.has(item))
console.log(result)

Map

ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map的属性和方法:

  • size 返回Map的元素个数
  • set 增加一个新元素,返回当前Map
  • get 返回键名对象的键值
  • has 检测Map中是否包含某个元素,返回boolean
  • clear 清空集合,返回undefined
//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
 ['name','guigu'],
 ['slogon','不断提高行业标准']
]);


//属性和方法
//获取映射元素的个数
console.log(m2.size);
//添加映射值
console.log(m2.set('age', 6));
//获取映射值
console.log(m2.get('age'));
//检测是否有该映射
console.log(m2.has('age'));
//清除
console.log(m2.clear());

class类

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

知识点:

  • class 声明类
  • constructor 定义构造函数初始化
  • extends 继承父类
  • super 调用父级构造方法
  • static 定义静态方法和属性(静态方法只能通过类访问,不能通过实例访问,不同于java)
  • 父类方法可以重写
//父类
class Phone {
     //构造方法 名字不能修改
     constructor(brand, color, price) {
     this.brand = brand;
     this.color = color;
     this.price = price;
     }

     //对象方法 方法必须使用该语法, 不能使用 ES5 的对象完整形式
     call() {
        console.log('我可以打电话!!!')
     }

    // get 和 set  
    get price(){
        console.log("价格属性被读取了");
        return 'iloveyou';
    }

    set price(newVal){
        console.log('价格属性被修改了');
    }
}

let phone = new Phone()
// 触发set方法
phone.price = "xxx"

// 触发get方法
console.log(phone.price)

//子类
class SmartPhone extends Phone {
     constructor(brand, color, price, screen, pixel) {
     super(brand, color, price);
     this.screen = screen;
     this.pixel = pixel;
     }

     //子类方法
     photo(){
        console.log('我可以拍照!!');
     }

     playGame(){
        console.log('我可以玩游戏!!');
     }

     //方法重写
     call(){
        console.log('我可以进行视频通话!!');
     }

     //静态方法
     static run(){
        console.log('我可以运行程序')
     }

     static connect(){
         console.log('我可以建立连接')
     }
}


//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone6s = new SmartPhone('苹果', '白色', 6088, '4.7inch','500w');
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法 静态方法只能通过类访问,不能通过实例访问,不同于java
SmartPhone.run();

数值扩展

ES6在Number对象上面,新增一个极小的常量Number.EPSILON。它表示1与大于1的最小浮点数之间的差。

对于64位浮点数来说,大于1的最小浮点数相当于二进制的1.00..001,小数点后面有连续51个零。这个值减去1之后,就等于2的-52次方

Number.EPSILON === Math.pow(2, -52) // true

Number.EPSILON // 2.220446049250313e-16
Number.EPSILON.toFixed(20) // "0.00000000000000022204"

0.1 + 0.2 // 0.30000000000000004

// 比较两个数是否相等
function equal (left, right) {
  return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}

0.1 + 0.2 === 0.3 // false
equal(0.1 + 0.2, 0.3) // true

1.1 + 1.3 === 2.4 // false
equal(1.1 + 1.3, 2.4) // true
  • Number.isFinite() 用来检查一个数值是否为有限的
  • Number.isNaN() 用来检查一个值是否为 NaN
  • Math.trunc()用于去除一个数的小数部分,返回整数部分
  • Number.isInteger() 用来判断一个数值是否为整数

ES6将全局方法parseIntparseFloat,移植到Number对象上面,使用不变 Number.parseInt()Number.parseFloat()

对象扩展

ES6新增了一些Object对象的方法

  • Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
  • Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
  • Object.setPrototypeOf 可以直接设置对象的原型
//1. Object.is 判断两个值是否完全相等 
console.log(Object.is(120, 120));// true 
console.log(Object.is(NaN, NaN));// true 
console.log(NaN === NaN);// false 

//2. Object.assign 对象的合并
const config1 = {
    host: 'localhost',
    port: 3306,
    name: 'root',
    pass: 'root',
    test: 'test'
};
const config2 = {
    host: 'http://obj.com',
    port: 33060,
    name: 'obj.com',
    pass: 'iloveyou',
    test2: 'test2'
}
console.log(Object.assign(config1, config2));
/* 结果
{
  host: 'http://obj.com',
  port: 33060,
  name: 'obj.com',
  pass: 'iloveyou',
  test: 'test',
  test2: 'test2'
}
*/

//3. Object.setPrototypeOf 设置原型对象  Object.getPrototypeof
const school = {
    name: '清华大学'
}
const cities = {
    xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);

模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

模块化的优势有以下几点:

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性

ES6之前的模块化规范有:

  • CommonJS => NodeJS、Browserify
  • AMD => requireJS
  • CMD => seaJS

模块功能主要由两个命令构成:

  • export 命令用于规定模块的对外接口
  • import 命令用于输入其他模块提供的功能

参考:Nodejs模块化

ECMASript7新特性

  • Array.prototype.includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
  • **指数操作符,用来实现幂运算,功能与 Math.pow 结果相同
// includes   indexOf
const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];

//判断
console.log(mingzhu.includes('西游记')); // true
console.log(mingzhu.includes('天龙八部')); // false

// 指数操作符
console.log(2 ** 10); // 1024 
console.log(Math.pow(2, 10)); // 1024

ECMASript8新特性

  • Object.keys()方法返回一个给定对象所有的键
  • Object.values()方法返回一个给定对象的所有可枚举属性值的数组
  • Object.entries()方法返回一个给定对象自身可遍历属性[key,value]的数组
  • Object.getOwnPropertyDescriptors 该方法返回指定对象所有自身属性的描述对象
//声明对象
const school = {
    name:"清华大学",
    cities:['北京','上海','深圳'],
    xueke: ['前端','Java','大数据','运维']
};

//获取对象所有的键
console.log(Object.keys(school));
//获取对象所有的值
console.log(Object.values(school));
//entries
console.log(Object.entries(school));

//创建 Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));

//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(school));
/* 输出结果
{
  name: {
    value: '清华大学',
    writable: true,
    enumerable: true,
    configurable: true
  },
  cities: {
    value: [ '北京', '上海', '深圳' ],
    writable: true,
    enumerable: true,
    configurable: true
  },
  xueke: {
    value: [ '前端', 'Java', '大数据', '运维' ],
    writable: true,
    enumerable: true,
    configurable: true
  }
}
*/

// 创建对象时指定对象属性描述符 create(原型对象,属性描述符对象)
const obj = Object.create(null, {
    name: {
        //设置值
        value: '清华大学',
        //属性特性
        writable: true,
        configurable: true,
        enumerable: true
    } 
});

async函数、await表达式

asyncawait两种语法结合可以让异步代码像同步代码一样

  • async函数的返回值为promise对象,promise对象的结果由async函数执行的返回值决定
  • await必须写在async函数中
  • await右侧的表达式一般为promise对象
  • await返回的是promise成功的值
  • awaitpromise失败了, 就会抛出异常, 需要通过try...catch捕获处理
//async 函数
async function fn(){
    // 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
    // 返回一个字符串
    // return 'asyncfun';
    // return;

    //抛出错误, 返回的结果是一个失败的 Promise
    // throw new Error('出错啦!');

    //返回的结果如果是一个 Promise 对象
    return new Promise((resolve, reject)=>{
        resolve('成功的数据');
        // reject("失败的错误");
    });
}

const result = fn();

//调用 then 方法
result.then(value => {
    console.log(value);
}, reason => {
    console.warn(reason);
})


//创建 promise 对象
const p = new Promise((resolve, reject) => {
    // resolve("用户数据");
    reject("失败啦!");
})

// await 要放在 async 函数中.
async function main() {
    try {
        let result = await p;
        //
        console.log(result);
    } catch (e) {
        console.log(e);
    }
}

//调用函数
main();

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/getJoke").then(value=>{
//     console.log(value);
// }, reason=>{})

// async 与 await 测试  axios
async function main(){
    //发送 AJAX 请求
    let result1 = await sendAJAX("https://v.api.aa1.cn/api/phone/guishu-api.php?phone=13333333333");
    console.log(result1);
    //再次测试
    let result2 = await sendAJAX('https://v.api.aa1.cn/api/api-mgc/index.php?msg=如何学习js')
    console.log(result2);
}

main();

ECMASript9新特性

Rest/Spread属性

Rest参数与spread扩展运算符在ES6中已经引入,不过ES6中只针对于数组,在ES9中为对象提供了像数组一样的rest参数和扩展运算符,可参考上面的解构赋值用法

正则表达式命名捕获组

//声明一个字符串
let str = '<a href="http://www.baidu.com">百度一下</a>';

//提取 url 与 『标签文本』
const reg = /<a href="(.*)">(.*)<\/a>/;
//执行
const result = reg.exec(str);

// 不使用分组命名
console.log(result);
console.log(result[1]);
console.log(result[2]);


// 使用分组命名
const reg2 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result2 = reg2.exec(str);

console.log(result2.groups.url);
console.log(result2.groups.text);

正则表达式反向断言

//声明字符串
let str = 'JS5211314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);

//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);

正则表达式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>/; 不使用dotAll模式
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);

ECMASript10新特性

  • Object.fromEntries 将map转换成对象
  • trimStart和trimEnd 分别清除字符串左边、右边的空格
  • Array.prototype.flat与flatMap 将多维数组转换成一维,跟其它语言的类型
  • Symbol.prototype.description 获取Symbol构造方法时传入的字符串
//二维数组
const result = Object.fromEntries([
    ['name','清华'],
    ['xueke', 'Java,大数据,前端,云计算']
]);

//Map
const m = new Map();
m.set('name','qinghua');
const result = Object.fromEntries(m);

//将多维数组转化为低位数组
const arr = [1,2,3,4,[5,6,[7,8,9]]];
//参数为深度 是一个数字
console.log(arr.flat(2));  

//flatMap
const arr = [1,2,3,4];
const result = arr.flatMap(item => [item * 10]);
console.log(result);

ECMASript11新特性

类的私有属性

用法跟其它语言类似比如java

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);

Promise.allSettled、Promise.all

//声明两个promise对象
const p1 = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve('商品数据 - 1');
    },1000)
});

const p2 = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve('商品数据 - 2');
        // reject('出错啦!');
    },1000)
});

// allsettled 方法 最终结果为成功的Promise,里面包含了所有的Promise结果
// const result = Promise.allSettled([p1, p2]);

// all 所有的Promise都成功了才算成功,只要有一个失败就算失败,失败的值就是这个值
// const res = Promise.all([p1, p2]);

console.log(res);

String.prototype.matchAll

优化了ECMASript9新特性中的正则

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);

可选链操作符

简化了层层判断空的操作

// ?.
function main(config){
    // const dbHost = config && config.db && config.db.host;
    // 使用可选链操作符写法
    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导入

实现按需加载,需要用到时候才加载

let fun = function(){
    // 使用import导入这个模块
    import('./xxx.js')
    .then(module => {
        // 导入之后的module就是js文件中export的对象,这里是export了一个hello方法
        module.hello();
    });
}

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))

globalThis对象

全局对象

posted @   wdszh  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示