前端进阶-js查漏补缺

作者 : admin 本文共16392个字,预计阅读时间需要41分钟 发布时间: 2024-06-17 共1人阅读

1、部分语法基础

1.1、let、const

特性:

// 1、暂时行死区
// 比如有这一个例子
let aa = "111"
function test(){
	console.log(aa)
	let aa = "22"
}
// 会报错引用错误,就是因为在函数test作用域内存在暂时性死区,如果把aa注释掉,则console.log(aa) 会打印 22

// 2、没有变量提升
// 3、不能刚重复定义
// 4、可以产生作用域

1.2、解构相关

数组解构

const [x,y,[c]] = [1, 2,[4,5,6]];
console.log(x,y,c); // 1 2 4

对象解构

const {name, age, address: {city, country}} = {
  name: 'John',
  age: 30,
  address: {
    city: 'New York',
    country: 'USA'
  }
}
console.log(name, age, city, country); // John 30  USA

字符串解构

// 字符串解构
const [a, b, c, d, e] = 'hello';
const {length : len} = 'hello';
console.log(a, b, c, d, e, len); // h e l l o  5

2、字符串扩展

2.1、判断字符串是否包含

// 字符串是否包含
const str = "hello"
console.log(str.includes('h'));  // true
// 字符串是否以指定字符串开头
console.log(str.startsWith('h')); // true
// 字符串是否以指定字符串结尾
console.log(str.endsWith('o'));  // true

// 以上三个方法都包含第二个参数,具体用法如下, 前两个都是从那个下标开始找,后一面一个是前n个字符串是否以 xx 结尾
console.log(str.includes('e', 1));  // true
console.log(str.startsWith('e', 1)); // true
// 这个的第二个参数稍微不一样,这是相当与str.slice(0, 4).endsWidth()
console.log(str.endsWith('l', 4));  // true

2.2、matchAll 与 match对比

// matchAll 使用 与 match 对比
// matchAll 返回一个迭代器,而 match 返回匹配到的数组

// 加入有這麽一個字符串 ul>li的,我们想要取出其中的值,做其他处理
const str = `
  
  • Item 1
  • Item 2
  • Item 3
` const regex = /
  • (?.*)/g; // 使用 match 方法 const matchResults = str.match(regex); console.log(matchResults.map((v) => v.replace(//g, ""))); // ["
  • Item 1
  • ", "
  • Item 2
  • ", "
  • Item 3
  • "] // 使用 matchAll 方法, 返回的是一个迭代器,可以通过forof 遍历, 也可以通过 [...matchAllResults].map 获取出值 const matchAllResults = str.matchAll(regex); for (const match of matchAllResults) { console.log(match.groups.content); // "Item 1", "Item 2", "Item 3" }

    3.3、重复

    // 字符串重复
    const str2 = "hello"
    console.log(str2.repeat(3));  // hellohellohello
    console.log(str2.repeat(0));  // ""
    console.log(str2.repeat("2"));  // "hellohello"
    
    /*
      字符填充 padStart、padEnd,前后填充
      第一个参数:填充完之后字符串的长度
      第二个参数:用于填充的字符串
     */
    const str = "Hello";
    console.log(str.padStart(10, "World")); // "WorldHello"
    const num = 123;
    console.log(num.toString().padStart(10, "0")); // "0000123"
    console.log(str.padEnd(11, "World")); // "HelloWorldW"
    console.log(num.toString().padEnd(10, "0")); // "1230000"
    

    3、数值

    3.1、数值进制

    // 进制数表示
    const num2 = 10
    const num3 = 0b1010 // 二进制
    const num4 = 0o12 // 八进制
    const num5 = 0xA  // 十六进制
    

    3.2、判断是否是 NaN 与 判断是否是有限值

    // 判断是否为NaN, Number.isNaN 不会对数字进行类型转换、对非数值都返回false
    console.log(Number.isNaN(10));  // false
    console.log(Number.isNaN("55"));  // false
    console.log(Number.isNaN(NaN));  // true
    // 全局方法 isNaN 会对要判断的值进行类型转换,转换成数字,再判断
    console.log(isNaN(10));  // false
    console.log(isNaN("55"));  // false
    console.log(isNaN(NaN));  // true
    console.log(isNaN("abc"));  // true
    
    // 判断是否为有限数 对于非数值都返回false
    console.log(Number.isFinite(10));  // true
    console.log(Number.isFinite("55"));  // false
    console.log(Number.isFinite(NaN));  // false
    console.log(Number.isFinite(Infinity));  // false
    console.log(Number.isFinite(100/0));  // false
    
    // 全局方法 isFinite 会对要判断的值进行类型转换,转换成数字,再判断, 对于转不成数值的字符串,会返回false
    console.log(isFinite(10));  // true
    console.log(isFinite("55"));  // true
    console.log(isFinite(NaN));  // false
    console.log(isFinite(Infinity));  // false
    console.log(isFinite(100/0));  // false
    console.log(isFinite("abc"));  // false

    3.3、bigInt

     

    /*
      bigInt
      由于number 的数值范围是-2^53 2^53,所以无法精确表示大于 2^53 的数值,所以就需要bigint这个数值类型
      */
    
    // bigint 不能与 number 进行运算
    // 因为 bigint 无法与 number 进行隐式转换
    
    let bigIntValue = 123n;
    let numberValue = 123;
    // console.log(bigIntValue + numberValue); // 报错
    console.log(bigIntValue + BigInt(numberValue)); // 246n
    
    // 但是可以进行比较
    console.log(bigIntValue == numberValue); // true
    console.log(bigIntValue === numberValue); // false
    

    4、数组扩展

    4.1、扩展运算符与剩余参数

    // 扩展运算符
    const arr1 = [1, 2, 3];
    const arr2 = [4, 5, 6];
    const arr3 = [...arr1, ...arr2]; // 浅层复制
    console.log(arr3); // [1, 2, 3, 4, 5, 6]
    
    // 剩余参数
    const [a, b, ...rest] = [1, 2, 3, 4, 5];
    console.log(a); // 1
    console.log(b); // 2
    console.log(rest); // [3, 4, 5]
    
    
    

    4.2、Array.from 与 Array.of

    
    // Array.from 可以将类数组转成数组
    function foo() {
    return Array.from(arguments);
    }
    console.log(foo(1, 2, 3)); // [1, 2, 3]
    // 还可以像 map 的回调函数那样使用
    const arr = Array.from([1, 2, 3], x => x \* 2);
    console.log(arr); // [2, 4, 6]
    
    // Array.of 用于创建一个具有可变数量参数的新数组实例,而不考虑参数化的数量
    console.log(Array.of(1, 2, 3)); // [1, 2, 3]
    console.log(Array.of(3)); // [3]
    // 与 Array 构造函数不同,Array 当只有一个参数的情况下,返回的是一个长度为 n 的空数组
    console.log(Array(3)); // [ , , ]

    4.3、fill

    // fill
    const arr6 = [1, 2, 3, 4, 5];
    arr6.fill(0, 1, 3); // 将索引 1 到索引 3 的元素替换为 0
    console.log(arr6); // [1, 0, 0, 4, 5]
    // fill 方法还可以用于数组的初始化
    const arr7 = new Array(5).fill(0); // 创建一个长度为 5 的空数组
    console.log(arr7); // [0, 0, 0, 0, 0]

    4.4、find、findIndex、findLast、findLastIndex

    
    // find 与 findIndex 查找满足指定条件的第一个元素,分别返回该元素和索引
    const arr4 = [1, 2, 3, 4, 5];
    const found = arr4.find(x => x > 3); // 返回值
    console.log(found); // 4
    const foundIndex = arr4.findIndex(x => x > 3); // 返索引
    console.log(foundIndex); // 3
    
    // findLast 与 findLastIndex 查找满足指定条件的最后一个元素,分别返回该元素和索引,需要注意的是 node 版本需要比较新的版本,才支持这两个方法,比如 18.17.1
    const arr5 = [1, 2, 3, 4, 5];
    const foundLast = arr5.findLast(x => x > 3); // 返回值
    console.log(foundLast); // 5
    const foundLastIndex = arr5.findLastIndex(x => x > 3); // 返索引
    console.log(foundLastIndex); // 4

    4.5、flat、flatMap

    // flat flatMap
    const arr8 = [1, 2, [3, 4, [5, 6]]];
    const flatArr = arr8.flat(); // 默认只会将数组拉平一层
    console.log(flatArr); // [1, 2, 3, 4, [5, 6]]
    const flatArr2 = arr8.flat(2); // 拉平多层
    console.log(flatArr2); // [1, 2, 3, 4, 5, 6]
    // key-map 的数组对象数组, 可以使用 flatMap 来扁平化
    const arr9 = [{name: 'xx', list: [1,2,3]}, {name: 'yy', list: [4,5,6]}];
    const flatMapArr = arr9.flatMap(x => x.list); // 会将每个 list 扁平化,相当于先调用map,再 flat
    console.log(flatMapArr); // [1, 2, 3, 4, 5, 6]

    5、对象扩展

    5.1、扩展运算符

    // 扩展运算符
    const person1 = {
    name: 'John',
    age: 30
    };
    const person2 = {
    ...person1,
    name: 'Jane'
    };
    console.log(person2); // 输出: { name: 'Jane', age: 30 }

    5.2、Object.assign

    // Object.assign()
    const person3 = {
    name: 'John'
    };
    const person4 = {
    age: 30
    };
    const person5 = {
    course: 99
    };
    Object.assign(person3, person4, person5);
    console.log(person3); // 输出: { name: 'John', age: 30, course: 99}

    5.3、Object.is

    // Object.is
    const person6 = {
    name: 'John',
    age: 30
    };
    const person7 = {
    name: 'John',
    age: 30
    }
    console.log(Object.is(person6, person7)); // 输出: false
    console.log(Object.is(NaN, NaN)); // 输出: true
    console.log(Object.is(+0, -0)); // 输出: false
    // 与 === 运算符的区别
    console.log(+0 === -0); // 输出: true
    console.log(NaN === NaN); // 输出: false

    5.4、Object.fromEntries

    // Object.fromEntries() 方法把键值对列表转换为一个对象。
    // 例如,将一个 Map 结构转换为对象:
    const entries = new Map([
      ['foo', 'bar'],
    ])
    console.log(Object.fromEntries(entries)); // { foo: 'bar' }
    
    
    // 用法2
    const obj = {
      name: 'John',
      age: 30,
      city: 'New York'
    }
    
    const keyValues = Object.entries(obj);
    console.log(keyValues); // [ [ 'name', 'John' ], [ 'age', 30 ], [ 'city', 'New York' ] ]
    console.log(Object.fromEntries(keyValues)); // { name: 'John', age: 30, city: 'New York' }
    
    // 用法3
    // 将一个 URLSearchParams 结构转换为对象:
    const paramsString = 'q=URLUtils.searchParams&topic=api';
    const searchParams = new URLSearchParams(paramsString);
    // 当然也可以像这样获取 searchParams.get
    console.log(searchParams.get('q')); // URLUtils.searchParams
    console.log(searchParams.get('topic')); // api
    console.log(Object.fromEntries(searchParams)); // { q: 'URLUtils.searchParams', topic: 'api' }
    
    
    
    

    6、函数扩展

    6.1、参数默认值与剩余参数

    // 函数参数默认值,注意假如有多个参数,默认值只能从最后开始放
    function greet(name = 'World') {
      console.log(`Hello, ${name}!`);
    }
    greet(); // 输出:Hello, World!
    greet('Alice'); // 输出:Hello, Alice!
    
    // 剩余参数,主要是平替 arguments
    function sum(...nums) {
      return nums.reduce((a, b) => a + b, 0);
    }
    console.log(sum(1, 2, 3, 4, 5)); // 输出:15
    function printNums(x, y, ...nums) {
      console.log(x, y, nums);
    }
    printNums(1, 2, 3, 4, 5); // 输出:1 2 [3, 4, 5]

    6.2、箭头函数

    /*
      箭头函数, 当只有一个参数时,可以省略小括号,当函数体只有一个表达式时,可以省略大括号和 return 关键字
      如果返回值是对象,需要用小括号包起来
      没有this(与上下文同一个),无法访问arguments, 无法作为构造函数
     */
    const add = (a, b) => a + b;
    console.log(add(1, 2)); // 输出:3

    7、Symbol

    7.1、Symbol基础使用

    // 创建Symbol
    const sym1 = Symbol();
    const sym2 = Symbol('key'); // 带有描述的字符串
    // console.log(sym1 > "666");  //  Cannot convert a Symbol value to a number
    // 显示调用 toString
    console.log(sym2.toString() + "666"); // Symbol(key)666
    // 隐式转换boolean
    if (sym2) {
      console.log("symbol is true");  // symbol is true
    }
    
    
    // symbol 作为对象属性名,就不会出现属性覆盖的情况了
    const sym3 = Symbol();
    const obj = {};
    obj[sym3] = "symbol property";
    console.log(obj[sym3]);  // symbol property
    const obj1 = {...obj}
    console.log(obj1[sym3]);  // symbol property
    // 一些防止意外更改的属性,,可以传一个字符串作为symbol描述,方便查看对象的时候区别那个属性
    const keys = {
      name: Symbol("name"),
      age: Symbol("age"),
      gender: Symbol("gender"),
      hobby: Symbol("hobby")
    }
    
    const obj2 = {
      [keys.name]: "张三",
      [keys.age]: 18,
      [keys.gender]: "男",
      [keys.hobby]: "篮球",
      other: "其他"
    }
    console.log(obj2[keys.name]);  // 张三
    
    // 不能forin遍历,这块的结果是啥也不打印
    for (const key in obj2) {
      console.log(key);
    }
    
    // 能用Object.getOwnPropertySymbols获取
    console.log(Object.getOwnPropertySymbols(obj2));  // [Symbol(name), Symbol(age), Symbol(gender), Symbol(hobby)]
    // 也可以用Reflect.ownKeys
    console.log(Reflect.ownKeys(obj2));  // [ 'other', Symbol(name), Symbol(age), Symbol(gender), Symbol(hobby) ]
    
    

    7.2、Symbol 作为常量使用

    /*
      symbol 作为常量, 为啥要这么是用,就是为了避免本来定义的常量的情况下
      例如 const COLOR_RED = "red"; 然後在用的时候非 getComplement("red")这么用,而不是getComplement(COLOR_RED)这么用
      使用symbol 作为常量,可以防止上面的问题
    */
    const COLOR_RED = Symbol();
    const COLOR_GREEN = Symbol();
    
    function getComplement(color) {
      switch (color) {
        case COLOR_RED:
          return "RED";
        case COLOR_GREEN:
          return "GREEN";
        default:
      }
    }
    
    // 测试
    console.log(getComplement(COLOR_RED));  // COLOR_GREEN
    console.log(getComplement(COLOR_GREEN));  // COLOR_RED
    
    // Symbol 获取描述符的方法
    const sym = Symbol('name');
    console.log(sym.description); // 输出 "name"

    8、iterator

    Symbol.iterator的作用
     *  1、是为各种数据结构,提供一个统一的、简便的访问接口
     *  2、是使得数据结构的成员能够按某种次序排列
     *  3、ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费
     *  4、一个数据结构只要部署了Iterator接口,我们就称这种数据结构是“可遍历的”
     *  5、原生具有迭代器的数据结构 Array Map Set String NodeList arguments 后面两个是伪数组

    8.1、基础使用

    // 获取迭代器
    const arr = ["a", "b", "c"];
    const iter = arr[Symbol.iterator]();
    // 使用next方法遍历
    console.log(iter.next()); // { value: 'a', done: false }
    console.log(iter.next()); // { value: 'b', done: false }
    console.log(iter.next()); // { value: 'c', done: false }
    console.log(iter.next()); // { value: undefined, done: true }
    
    // 线性对象 增加迭代器, 则对象就可以使用for...of循环遍历了
    const obj = {
      0: "a",
      1: "b",
      2: "c",
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    }
    for (const c of obj) {
      console.log(c);
    }
    

    8.2、自定义迭代器

    // 自定义迭代器
    const obj2 = {
      data: ["a", "b", "c"],
      [Symbol.iterator]() {
        let index = 0;
        return {
          next: () => ({
            value: this.data[index++],
            done: index > this.data.length
          })
        }
      }
    }
    const iter2 = obj2[Symbol.iterator]();
    console.log(iter2.next()); // { value: 'a', done: false }
    console.log(iter2.next()); // { value: 'b', done: false }
    console.log(iter2.next()); // { value: 'c', done: false }
    console.log(iter2.next()); // { value: undefined, done: true }
    
    // 配合扩展运算符,或者Array.from,容有迭代器的数据结构,都会自动转成数组
    const arr2 = [...obj2];
    console.log(arr2); // ['a', 'b', 'c']
    console.log(Array.from(obj2)); // ['a', 'b', 'c']

    9、set

    9.1、基础使用

    // set 介绍及其使用
    // 创建一个Set对象
    const mySet = new Set();
    
    // 添加元素
    mySet.add(1);
    mySet.add(2);
    mySet.add(3);
    
    // 检查元素是否存在
    console.log(mySet.has(2)); // 输出 true
    console.log(mySet.has(4)); // 输出 false
    
    // 删除元素
    mySet.delete(2);
    
    // 获取Set的大小
    console.log(mySet.size); // 输出 2
    
    // 遍历Set
    for (let value of mySet) {
      console.log(value); // 输出 1, 3
    }

    9.2、进阶使用

    // 将Set转换为数组
    console.log(Array.from(mySet)); // 输出 [1, 3]
    console.log([...mySet]); // 输出 [1, 3]
    
    // 清空Set
    mySet.clear();
    
    // 检查Set是否为空
    console.log(mySet.size === 0); // 输出 true
    
    // 合并Set
    const set1 = new Set([1, 2, 3]);
    const set2 = new Set([2, 3, 4]);
    const unionSet = new Set([...set1, ...set2]);
    console.log(unionSet); // 输出 Set { 1, 2, 3, 4 }
    
    // keys values entries set的键、值都是相同的
    const mySet1 = new Set(['a', 'b', 'c']);
    
    for (let key of mySet1.keys()) {
      console.log(key); // 输出 'a', 'b', 'c'
    }
    
    for (let value of mySet1.values()) {
      console.log(value); // 输出 'a', 'b', 'c'
    }
    
    for (let entry of mySet1.entries()) {
      console.log(entry); // 输出 ['a', 'a'], ['b', 'b'], ['c', 'c']
    }
    
    // 结合set实现一个去重复杂数组
    function uniqueArray(arr) {
      const uniSet = new Set();
      return arr.filter((item)=>{
        const str = JSON.stringify(item);
        if (uniSet.has(str)) {
          return false;
        }else{
          uniSet.add(str);
          return true;
        }
      })
    }
    
    const arr = [1, 1, 3, 4, {name:12}, {name:12}, [1,2], [1,2]];
    console.log( uniqueArray(arr)); // [ 1, 3, 4, { name: 12 }, [ 1, 2 ] ]

    10、map

    10.1、基础使用

    // 创建一个 Map 对象
    
    constkeyObj= {name:11}
    
    constmyMap=newMap([
    
    ["aa", 11],
    
    ["bb", 22],
    
    [keyObj, 33],
    
    [55, 33],
    
    ]);
    
    // 添加键值对
    
    myMap.set("cc", 44);
    
    console.log(myMap); // Map(5) { 'aa' => 11, 'bb' => 22, { name: 11 } => 33, 55 => 33, 'cc' => 44 }
    
    // 是否包含某个键
    
    console.log(myMap.has("aa")); // true
    
    // 删除键值对
    
    myMap.delete(keyObj);
    
    console.log(myMap); // Map(4) { 'aa' => 11, 'bb' => 22, 55 => 33, 'cc' => 44 }
    
    // 获取键值对数量
    
    console.log(myMap.size); // 4
    
    // 遍历 Map
    
    for (constitemofmyMap) {
    
    console.log(item); // 输出键值对 [ 'aa', 11 ] [ 'bb', 22 ] [ 55, 33 ] [ 'cc', 44 ]
    
    }
    
    // 转成数组
    
    console.log([...myMap]); // [ [ 'aa', 11 ], [ 'bb', 22 ], [ 55, 33 ], [ 'cc', 44 ] ]
    
    console.log(Array.from(myMap)); // [ [ 'aa', 11 ], [ 'bb', 22 ], [ 55, 33 ], [ 'cc', 44 ] ]
    
    // 清空 Map
    
    myMap.clear();
    
    console.log(myMap); // Map(0) {}

    11、Proxy

    11.1、基础使用

    /*
      Proxy 它的作用实在对象与对象的属性之间架设一个代理,用于对对象的操作进行拦截和改写,
      它提供了一种机制,可以拦截并修改对象的任意属性,或者对属性进行操作。
     */
    
    const target = {
      name: 'John',
      age: 30
    };
    
    const proxy = new Proxy(target, {
      get: function(target, property, receiver) {
        console.log(`Getting ${property}`);
        return target[property];
      },
      set: function(target, property, value, receiver) {
        console.log(`Setting ${property} to ${value}`);
        target[property] = value;
      }
    })
    console.log(proxy.name);  // 输出 "Getting name" 和 "John"
    proxy.age = 40;  // 输出 "Setting age to 40"
    console.log(target.age); // 输出 40,target会与proxy同时改变

    12、Reflect

     Reflect 可以用于获取目标对象的行为,他与Object类似,但是更加易读,为了操作
     对象提供了一种更加优雅的方式,它的方法与Proxy时对应的,代替Object 的部分方法

     12.1、基础使用

    const obj = {
      name: 'why',
      age: 18
    }
    
    /**
     * 获取与设置对象属性
     */
    // 获取对象上的属性
    const name = Reflect.get(obj, 'name')
    console.log(name) // why
    // 设置对象的属性
    Reflect.set(obj, 'address', '北京市')
    
    /**
     * 函数代替命令式的写法
     * delete obj.name --> Reflect.deleteProperty(obj, 'name')
     * name in obj --> Reflect.has(obj, 'name')
     */
    // 判断对象上是否有指定属性
    const hasName = Reflect.has(obj, 'name')
    console.log(hasName) // true
    
    // 删除对象的属性
    Reflect.deleteProperty(obj, 'age')
    console.log(obj); // { name: 'why', address: '北京市' }
    

    12.2、与proxy使用

    /**
     * 一般是与 proxy一起使用的
     */
    // 代理对象
    const arr = [1,2,3]
    // 代理配置
    const proxy = new Proxy(arr, {
      get(target, key) {
        // 下面是执行被代理对象的自己的行为,在这之前可以拦截一些操作
        console.log("get", target, key); //get [ 1, 2, 3 ] push get [ 1, 2, 3 ] length
        return Reflect.get(target, key)
      },
      set(target, key, value) {
        console.log(target, key, value); // [ 1, 2, 3 ] push 4 [ 1, 2, 3, 4 ] length 4
        // 下面是执行被代理对象的自己的行为,在这之前可以拦截一些操作
        return Reflect.set(target, key, value)
      }
    })
    proxy.push(4);
    
    
    
    
    // 设置对象的属性的操作
    const obj2 = {
      name: 'kobe',
      age: 30
    }
    
    // 设置属性
    Reflect.defineProperty(obj2, 'address', {
      value: '上海市',
      writable: false, // 是否可以修改
    })
    
    
    
    
    
    /*
      修改了Object部分方法分返回结果
      Object.defineProperty() 如果执行失败,会抛出错误  -> Reflect.defineProperty()执行失败则会返回false
      下面搞两个例子作对比
    */
    console.log(
      Reflect.defineProperty(obj2, 'address', {
        value: '广州市',
      })
    ); // false
    
    Object.defineProperty(obj2, 'xxx', {
      value: 'xx',
      writable: false, // 是否可以修改
    })
    Object.defineProperty(obj2, 'xxx', {
      value: '66',
    }) // 报错 Cannot redefine property: xxx
    
    

    13、class

    13.1、私有及静态属性

    /**
     * class 语法糖使用
     * 可以写 get 、 set 方法, 但是实际中不建议使用,这里就不写相关 demo 了
     * 也可以写静态方法 static 开头
     */
    class Person {
      static money = 100; // 静态属性
      static getMoney() { // 静态方法
        return Person.money;
      }
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    
      greet() {
        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
      }
    }
    
    const person = new Person('John', 25);
    person.greet(); // 输出:Hello, my name is John and I am 25 years old.
    console.log(Person.getMoney(), Person.money); // 输出 100 100
    
    // 继承, 父类的静态方法、属性也会被继承
    class Student extends Person {
      constructor(name, age, grade) {
        // 调用父类的构造函数
        super(name, age);
        this.grade = grade;
      }
    
      // 可以重写父类的方法
      greet() {
        // 可以通过 super 访问父类的方法
        super.greet();
        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old. I am in grade ${this.grade}.`);
      }
    
      // 也可以添加自己的方法
      study() {
        console.log(`${this.name} is studying.`);
      }
    }
    
    const student = new Student('Alice', 18, 'A');
    student.greet(); // 输出:Hello, my name is Alice and I am 18 years old. Hello, my name is Alice and I am 18 years old. I am in grade A.
    student.study(); // 输出:Alice is studying.
    console.log(Student.money, Student.getMoney()); // 输出 100 100

    14、正则扩展

    14.1、命名捕获组(?)

    const str = '百度';
    // 捕获了两个命名组,分别是 url 和 text
    const reg = /.*)">(?.*)/;
    
    const result = reg.exec(str);
    console.log(result.groups.url); // https://www.baidu.com
    console.log(result.groups.text); // 百度

    14.2、开始结束索引

    var str = "今天是2024-06-11";
    var regex = /(?\d{4})-(?\d{2})-(?\d{2})/d;
    
    /**
     * 输出 includes就是 各个匹配组的开始及结束下标
     * [
      '2024-06-11',
      '2024',
      '06',
      '11',
      index: 3,
      input: '今天是2024-06-11',
      groups: [Object: null prototype] { year: '2024', month: '06', day: '11' },
      indices: [
        [ 3, 13 ],    // "2024-06-11" 的开始即结束下标
        [ 3, 7 ],
        [ 8, 10 ],
        [ 11, 13 ],
        groups: [Object: null prototype] {
          year: [Array],
          month: [Array],
          day: [Array]
        }
      ]
    ]
     */
    console.log(regex.exec(str));

    15、异步迭代器

    15.1、使用

    主要是与for await结合使用

     // 同步迭代器、简单使用
    function *gen(){
      yield 1;
      yield 2;
      yield 3;
    }
    
    for(let value of gen()){
      console.log(value); // 输出:1 2 3
    }
    
    // promise 中有定時器
    function timer(time){
      return new Promise(resolve => {
        setTimeout(()=>{
          resolve(`data-${time}`)
        }, time);
      });
    }
    
    
    // 同步迭代器返回 promise
    function *gen2(){
      yield timer(1000);
      yield timer(2000);
      yield timer(3000);
    }
    
    const g = gen2();
    
    for(let value of g){
      console.log(value); // 输出:Promise {  } Promise {  } Promise {  }
    }
    
    // 异步生成器
    async function *gen3(){
      yield timer(1000);
      yield timer(2000);
      yield timer(3000);
    }
    
    async function test(){
      const g3 = gen3();
      // 三个异步生成器生成的 任务,这里不是同步执行的,是分别执行完,再从头开始执行的
      // 与普通的promise 普通的是并行执行的,分别会在第1、2、3秒输出结果
      const arr = [g3.next(), g3.next(), g3.next()];
      for await(const req of arr){
        console.log(req.value); // 第一秒的时候: data-1000 第三秒的时候:data-2000 第六秒的时候:data-3000
      }
    }
    test()
    
    
    
    
    

    16、ES11

    16.1、动态导入

    
    
    
      
      
      异步迭代
    
    
      
    
    

    16.2、模块化开发相关

    module.js

    export default {
      name: 666
    }
    
    export function test(){}

    统一管理模块

    export * as obj from "xxx"	// 从其他模块导入东西在当前模块,并且与当前模块的东西一并导出去,在其他的地方使用的时候就引入当前模块即可
    

    16.3、globalThis

    提供一种标准方式,让我们在不同环境可以获取到对应的顶层对象、比如像浏览器环境的window、node环境的global等

    17、ES12 及之后的

    17.1、逻辑运算符

    // &&=
    let a = 10
    a &&=20
    console.log(a) // 20
    
    let b = 0
    b &&=20
    console.log(b) // 0
    
    // ||=
    let c = 10
    c ||=20
    console.log(c) // 10
    
    let d = 0
    d ||=20
    console.log(d) // 20
    
    // ??=
    let e = 10
    e ??=20
    console.log(e) // 10
    
    let f = 0
    f ??=20
    console.log(f) // 0
    
    // 示例
    let user = null
    user ??=666
    console.log(user) // 666
    
    
    
    

    17.2、数值分隔符

    // 数值分隔符
    let num = 123_456_789;
    console.log(num, num === 123456789); // 输出: 123456789 true
    
    let num2 = 123.456;
    console.log(num2); // 输出: 123.456
    
    let num3 = 123_456.789;
    console.log(num3); // 输出: 123456.789
    
    // 其他进制也可以这样表示
    let binaryNum = 0b1010_1010;
    console.log(binaryNum); // 输出: 170
    

    17.3、WeakSet

    
    
    
      
      
      weakSet
    
    
      
    
    

    17.4、weakMap

    
    
    
      
      
      异步迭代
    
    
      
    
    

    以上便是本次ES6 查漏补缺的记录,欢迎留言交流,共勉

    本站无任何商业行为
    个人在线分享 » 前端进阶-js查漏补缺
    E-->