• 前端进阶-js查漏补缺


    1、部分语法基础

    1.1、let、const

    1. 特性:
    2. // 1、暂时行死区
    3. // 比如有这一个例子
    4. let aa = "111"
    5. function test(){
    6. console.log(aa)
    7. let aa = "22"
    8. }
    9. // 会报错引用错误,就是因为在函数test作用域内存在暂时性死区,如果把aa注释掉,则console.log(aa) 会打印 22
    10. // 2、没有变量提升
    11. // 3、不能刚重复定义
    12. // 4、可以产生作用域

    1.2、解构相关

    数组解构

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

    对象解构

    1. const {name, age, address: {city, country}} = {
    2. name: 'John',
    3. age: 30,
    4. address: {
    5. city: 'New York',
    6. country: 'USA'
    7. }
    8. }
    9. console.log(name, age, city, country); // John 30 USA

    字符串解构

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

    2、字符串扩展

    2.1、判断字符串是否包含

    1. // 字符串是否包含
    2. const str = "hello"
    3. console.log(str.includes('h')); // true
    4. // 字符串是否以指定字符串开头
    5. console.log(str.startsWith('h')); // true
    6. // 字符串是否以指定字符串结尾
    7. console.log(str.endsWith('o')); // true
    8. // 以上三个方法都包含第二个参数,具体用法如下, 前两个都是从那个下标开始找,后一面一个是前n个字符串是否以 xx 结尾
    9. console.log(str.includes('e', 1)); // true
    10. console.log(str.startsWith('e', 1)); // true
    11. // 这个的第二个参数稍微不一样,这是相当与str.slice(0, 4).endsWidth()
    12. console.log(str.endsWith('l', 4)); // true

    2.2、matchAll 与 match对比

    1. // matchAll 使用 与 match 对比
    2. // matchAll 返回一个迭代器,而 match 返回匹配到的数组
    3. // 加入有這麽一個字符串 ul>li的,我们想要取出其中的值,做其他处理
    4. const str = `
      • Item 1
    5. Item 2
  • Item 3
  • `
  • const regex = /
  • (?.*)<\/li>/g;
  • // 使用 match 方法
  • const matchResults = str.match(regex);
  • console.log(matchResults.map((v) => v.replace(/<\/?li>/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、重复

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

    3、数值

    3.1、数值进制

    1. // 进制数表示
    2. const num2 = 10
    3. const num3 = 0b1010 // 二进制
    4. const num4 = 0o12 // 八进制
    5. const num5 = 0xA // 十六进制

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

    1. // 判断是否为NaN, Number.isNaN 不会对数字进行类型转换、对非数值都返回false
    2. console.log(Number.isNaN(10)); // false
    3. console.log(Number.isNaN("55")); // false
    4. console.log(Number.isNaN(NaN)); // true
    5. // 全局方法 isNaN 会对要判断的值进行类型转换,转换成数字,再判断
    6. console.log(isNaN(10)); // false
    7. console.log(isNaN("55")); // false
    8. console.log(isNaN(NaN)); // true
    9. console.log(isNaN("abc")); // true
    10. // 判断是否为有限数 对于非数值都返回false
    11. console.log(Number.isFinite(10)); // true
    12. console.log(Number.isFinite("55")); // false
    13. console.log(Number.isFinite(NaN)); // false
    14. console.log(Number.isFinite(Infinity)); // false
    15. console.log(Number.isFinite(100/0)); // false
    16. // 全局方法 isFinite 会对要判断的值进行类型转换,转换成数字,再判断, 对于转不成数值的字符串,会返回false
    17. console.log(isFinite(10)); // true
    18. console.log(isFinite("55")); // true
    19. console.log(isFinite(NaN)); // false
    20. console.log(isFinite(Infinity)); // false
    21. console.log(isFinite(100/0)); // false
    22. console.log(isFinite("abc")); // false

    3.3、bigInt

     

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

    4、数组扩展

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

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

    4.2、Array.from 与 Array.of

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

    4.3、fill

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

    4.4、find、findIndex、findLast、findLastIndex

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

    4.5、flat、flatMap

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

    5、对象扩展

    5.1、扩展运算符

    1. // 扩展运算符
    2. const person1 = {
    3. name: 'John',
    4. age: 30
    5. };
    6. const person2 = {
    7. ...person1,
    8. name: 'Jane'
    9. };
    10. console.log(person2); // 输出: { name: 'Jane', age: 30 }

    5.2、Object.assign

    1. // Object.assign()
    2. const person3 = {
    3. name: 'John'
    4. };
    5. const person4 = {
    6. age: 30
    7. };
    8. const person5 = {
    9. course: 99
    10. };
    11. Object.assign(person3, person4, person5);
    12. console.log(person3); // 输出: { name: 'John', age: 30, course: 99}

    5.3、Object.is

    1. // Object.is
    2. const person6 = {
    3. name: 'John',
    4. age: 30
    5. };
    6. const person7 = {
    7. name: 'John',
    8. age: 30
    9. }
    10. console.log(Object.is(person6, person7)); // 输出: false
    11. console.log(Object.is(NaN, NaN)); // 输出: true
    12. console.log(Object.is(+0, -0)); // 输出: false
    13. // 与 === 运算符的区别
    14. console.log(+0 === -0); // 输出: true
    15. console.log(NaN === NaN); // 输出: false

    5.4、Object.fromEntries

    1. // Object.fromEntries() 方法把键值对列表转换为一个对象。
    2. // 例如,将一个 Map 结构转换为对象:
    3. const entries = new Map([
    4. ['foo', 'bar'],
    5. ])
    6. console.log(Object.fromEntries(entries)); // { foo: 'bar' }
    7. // 用法2
    8. const obj = {
    9. name: 'John',
    10. age: 30,
    11. city: 'New York'
    12. }
    13. const keyValues = Object.entries(obj);
    14. console.log(keyValues); // [ [ 'name', 'John' ], [ 'age', 30 ], [ 'city', 'New York' ] ]
    15. console.log(Object.fromEntries(keyValues)); // { name: 'John', age: 30, city: 'New York' }
    16. // 用法3
    17. // 将一个 URLSearchParams 结构转换为对象:
    18. const paramsString = 'q=URLUtils.searchParams&topic=api';
    19. const searchParams = new URLSearchParams(paramsString);
    20. // 当然也可以像这样获取 searchParams.get
    21. console.log(searchParams.get('q')); // URLUtils.searchParams
    22. console.log(searchParams.get('topic')); // api
    23. console.log(Object.fromEntries(searchParams)); // { q: 'URLUtils.searchParams', topic: 'api' }

    6、函数扩展

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

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

    6.2、箭头函数

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

    7、Symbol

    7.1、Symbol基础使用

    1. // 创建Symbol
    2. const sym1 = Symbol();
    3. const sym2 = Symbol('key'); // 带有描述的字符串
    4. // console.log(sym1 > "666"); // Cannot convert a Symbol value to a number
    5. // 显示调用 toString
    6. console.log(sym2.toString() + "666"); // Symbol(key)666
    7. // 隐式转换boolean
    8. if (sym2) {
    9. console.log("symbol is true"); // symbol is true
    10. }
    11. // symbol 作为对象属性名,就不会出现属性覆盖的情况了
    12. const sym3 = Symbol();
    13. const obj = {};
    14. obj[sym3] = "symbol property";
    15. console.log(obj[sym3]); // symbol property
    16. const obj1 = {...obj}
    17. console.log(obj1[sym3]); // symbol property
    18. // 一些防止意外更改的属性,,可以传一个字符串作为symbol描述,方便查看对象的时候区别那个属性
    19. const keys = {
    20. name: Symbol("name"),
    21. age: Symbol("age"),
    22. gender: Symbol("gender"),
    23. hobby: Symbol("hobby")
    24. }
    25. const obj2 = {
    26. [keys.name]: "张三",
    27. [keys.age]: 18,
    28. [keys.gender]: "男",
    29. [keys.hobby]: "篮球",
    30. other: "其他"
    31. }
    32. console.log(obj2[keys.name]); // 张三
    33. // 不能forin遍历,这块的结果是啥也不打印
    34. for (const key in obj2) {
    35. console.log(key);
    36. }
    37. // 能用Object.getOwnPropertySymbols获取
    38. console.log(Object.getOwnPropertySymbols(obj2)); // [Symbol(name), Symbol(age), Symbol(gender), Symbol(hobby)]
    39. // 也可以用Reflect.ownKeys
    40. console.log(Reflect.ownKeys(obj2)); // [ 'other', Symbol(name), Symbol(age), Symbol(gender), Symbol(hobby) ]

    7.2、Symbol 作为常量使用

    1. /*
    2. symbol 作为常量, 为啥要这么是用,就是为了避免本来定义的常量的情况下
    3. 例如 const COLOR_RED = "red"; 然後在用的时候非 getComplement("red")这么用,而不是getComplement(COLOR_RED)这么用
    4. 使用symbol 作为常量,可以防止上面的问题
    5. */
    6. const COLOR_RED = Symbol();
    7. const COLOR_GREEN = Symbol();
    8. function getComplement(color) {
    9. switch (color) {
    10. case COLOR_RED:
    11. return "RED";
    12. case COLOR_GREEN:
    13. return "GREEN";
    14. default:
    15. }
    16. }
    17. // 测试
    18. console.log(getComplement(COLOR_RED)); // COLOR_GREEN
    19. console.log(getComplement(COLOR_GREEN)); // COLOR_RED
    20. // Symbol 获取描述符的方法
    21. const sym = Symbol('name');
    22. 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、基础使用

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

    8.2、自定义迭代器

    1. // 自定义迭代器
    2. const obj2 = {
    3. data: ["a", "b", "c"],
    4. [Symbol.iterator]() {
    5. let index = 0;
    6. return {
    7. next: () => ({
    8. value: this.data[index++],
    9. done: index > this.data.length
    10. })
    11. }
    12. }
    13. }
    14. const iter2 = obj2[Symbol.iterator]();
    15. console.log(iter2.next()); // { value: 'a', done: false }
    16. console.log(iter2.next()); // { value: 'b', done: false }
    17. console.log(iter2.next()); // { value: 'c', done: false }
    18. console.log(iter2.next()); // { value: undefined, done: true }
    19. // 配合扩展运算符,或者Array.from,容有迭代器的数据结构,都会自动转成数组
    20. const arr2 = [...obj2];
    21. console.log(arr2); // ['a', 'b', 'c']
    22. console.log(Array.from(obj2)); // ['a', 'b', 'c']

    9、set

    9.1、基础使用

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

    9.2、进阶使用

    1. // 将Set转换为数组
    2. console.log(Array.from(mySet)); // 输出 [1, 3]
    3. console.log([...mySet]); // 输出 [1, 3]
    4. // 清空Set
    5. mySet.clear();
    6. // 检查Set是否为空
    7. console.log(mySet.size === 0); // 输出 true
    8. // 合并Set
    9. const set1 = new Set([1, 2, 3]);
    10. const set2 = new Set([2, 3, 4]);
    11. const unionSet = new Set([...set1, ...set2]);
    12. console.log(unionSet); // 输出 Set { 1, 2, 3, 4 }
    13. // keys values entries set的键、值都是相同的
    14. const mySet1 = new Set(['a', 'b', 'c']);
    15. for (let key of mySet1.keys()) {
    16. console.log(key); // 输出 'a', 'b', 'c'
    17. }
    18. for (let value of mySet1.values()) {
    19. console.log(value); // 输出 'a', 'b', 'c'
    20. }
    21. for (let entry of mySet1.entries()) {
    22. console.log(entry); // 输出 ['a', 'a'], ['b', 'b'], ['c', 'c']
    23. }
    24. // 结合set实现一个去重复杂数组
    25. function uniqueArray(arr) {
    26. const uniSet = new Set();
    27. return arr.filter((item)=>{
    28. const str = JSON.stringify(item);
    29. if (uniSet.has(str)) {
    30. return false;
    31. }else{
    32. uniSet.add(str);
    33. return true;
    34. }
    35. })
    36. }
    37. const arr = [1, 1, 3, 4, {name:12}, {name:12}, [1,2], [1,2]];
    38. console.log( uniqueArray(arr)); // [ 1, 3, 4, { name: 12 }, [ 1, 2 ] ]

    10、map

    10.1、基础使用

    1. // 创建一个 Map 对象
    2. constkeyObj= {name:11}
    3. constmyMap=newMap([
    4. ["aa", 11],
    5. ["bb", 22],
    6. [keyObj, 33],
    7. [55, 33],
    8. ]);
    9. // 添加键值对
    10. myMap.set("cc", 44);
    11. console.log(myMap); // Map(5) { 'aa' => 11, 'bb' => 22, { name: 11 } => 33, 55 => 33, 'cc' => 44 }
    12. // 是否包含某个键
    13. console.log(myMap.has("aa")); // true
    14. // 删除键值对
    15. myMap.delete(keyObj);
    16. console.log(myMap); // Map(4) { 'aa' => 11, 'bb' => 22, 55 => 33, 'cc' => 44 }
    17. // 获取键值对数量
    18. console.log(myMap.size); // 4
    19. // 遍历 Map
    20. for (constitemofmyMap) {
    21. console.log(item); // 输出键值对 [ 'aa', 11 ] [ 'bb', 22 ] [ 55, 33 ] [ 'cc', 44 ]
    22. }
    23. // 转成数组
    24. console.log([...myMap]); // [ [ 'aa', 11 ], [ 'bb', 22 ], [ 55, 33 ], [ 'cc', 44 ] ]
    25. console.log(Array.from(myMap)); // [ [ 'aa', 11 ], [ 'bb', 22 ], [ 55, 33 ], [ 'cc', 44 ] ]
    26. // 清空 Map
    27. myMap.clear();
    28. console.log(myMap); // Map(0) {}

    11、Proxy

    11.1、基础使用

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

    12、Reflect

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

     12.1、基础使用

    1. const obj = {
    2. name: 'why',
    3. age: 18
    4. }
    5. /**
    6. * 获取与设置对象属性
    7. */
    8. // 获取对象上的属性
    9. const name = Reflect.get(obj, 'name')
    10. console.log(name) // why
    11. // 设置对象的属性
    12. Reflect.set(obj, 'address', '北京市')
    13. /**
    14. * 函数代替命令式的写法
    15. * delete obj.name --> Reflect.deleteProperty(obj, 'name')
    16. * name in obj --> Reflect.has(obj, 'name')
    17. */
    18. // 判断对象上是否有指定属性
    19. const hasName = Reflect.has(obj, 'name')
    20. console.log(hasName) // true
    21. // 删除对象的属性
    22. Reflect.deleteProperty(obj, 'age')
    23. console.log(obj); // { name: 'why', address: '北京市' }

    12.2、与proxy使用

    1. /**
    2. * 一般是与 proxy一起使用的
    3. */
    4. // 代理对象
    5. const arr = [1,2,3]
    6. // 代理配置
    7. const proxy = new Proxy(arr, {
    8. get(target, key) {
    9. // 下面是执行被代理对象的自己的行为,在这之前可以拦截一些操作
    10. console.log("get", target, key); //get [ 1, 2, 3 ] push get [ 1, 2, 3 ] length
    11. return Reflect.get(target, key)
    12. },
    13. set(target, key, value) {
    14. console.log(target, key, value); // [ 1, 2, 3 ] push 4 [ 1, 2, 3, 4 ] length 4
    15. // 下面是执行被代理对象的自己的行为,在这之前可以拦截一些操作
    16. return Reflect.set(target, key, value)
    17. }
    18. })
    19. proxy.push(4);
    20. // 设置对象的属性的操作
    21. const obj2 = {
    22. name: 'kobe',
    23. age: 30
    24. }
    25. // 设置属性
    26. Reflect.defineProperty(obj2, 'address', {
    27. value: '上海市',
    28. writable: false, // 是否可以修改
    29. })
    30. /*
    31. 修改了Object部分方法分返回结果
    32. Object.defineProperty() 如果执行失败,会抛出错误 -> Reflect.defineProperty()执行失败则会返回false
    33. 下面搞两个例子作对比
    34. */
    35. console.log(
    36. Reflect.defineProperty(obj2, 'address', {
    37. value: '广州市',
    38. })
    39. ); // false
    40. Object.defineProperty(obj2, 'xxx', {
    41. value: 'xx',
    42. writable: false, // 是否可以修改
    43. })
    44. Object.defineProperty(obj2, 'xxx', {
    45. value: '66',
    46. }) // 报错 Cannot redefine property: xxx

    13、class

    13.1、私有及静态属性

    1. /**
    2. * class 语法糖使用
    3. * 可以写 get 、 set 方法, 但是实际中不建议使用,这里就不写相关 demo 了
    4. * 也可以写静态方法 static 开头
    5. */
    6. class Person {
    7. static money = 100; // 静态属性
    8. static getMoney() { // 静态方法
    9. return Person.money;
    10. }
    11. constructor(name, age) {
    12. this.name = name;
    13. this.age = age;
    14. }
    15. greet() {
    16. console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
    17. }
    18. }
    19. const person = new Person('John', 25);
    20. person.greet(); // 输出:Hello, my name is John and I am 25 years old.
    21. console.log(Person.getMoney(), Person.money); // 输出 100 100
    22. // 继承, 父类的静态方法、属性也会被继承
    23. class Student extends Person {
    24. constructor(name, age, grade) {
    25. // 调用父类的构造函数
    26. super(name, age);
    27. this.grade = grade;
    28. }
    29. // 可以重写父类的方法
    30. greet() {
    31. // 可以通过 super 访问父类的方法
    32. super.greet();
    33. console.log(`Hello, my name is ${this.name} and I am ${this.age} years old. I am in grade ${this.grade}.`);
    34. }
    35. // 也可以添加自己的方法
    36. study() {
    37. console.log(`${this.name} is studying.`);
    38. }
    39. }
    40. const student = new Student('Alice', 18, 'A');
    41. 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.
    42. student.study(); // 输出:Alice is studying.
    43. console.log(Student.money, Student.getMoney()); // 输出 100 100

    14、正则扩展

    14.1、命名捕获组(?<命名组名称>)

    1. const str = '百度';
    2. // 捕获了两个命名组,分别是 url 和 text
    3. const reg = /(?.*)<\/a>/;

    14.2、开始结束索引

    1. var str = "今天是2024-06-11";
    2. var regex = /(?\d{4})-(?\d{2})-(?\d{2})/d;
    3. /**
    4. * 输出 includes就是 各个匹配组的开始及结束下标
    5. * [
    6. '2024-06-11',
    7. '2024',
    8. '06',
    9. '11',
    10. index: 3,
    11. input: '今天是2024-06-11',
    12. groups: [Object: null prototype] { year: '2024', month: '06', day: '11' },
    13. indices: [
    14. [ 3, 13 ], // "2024-06-11" 的开始即结束下标
    15. [ 3, 7 ],
    16. [ 8, 10 ],
    17. [ 11, 13 ],
    18. groups: [Object: null prototype] {
    19. year: [Array],
    20. month: [Array],
    21. day: [Array]
    22. }
    23. ]
    24. ]
    25. */
    26. console.log(regex.exec(str));

    15、异步迭代器

    15.1、使用

    主要是与for await结合使用

    1. // 同步迭代器、简单使用
    2. function *gen(){
    3. yield 1;
    4. yield 2;
    5. yield 3;
    6. }
    7. for(let value of gen()){
    8. console.log(value); // 输出:1 2 3
    9. }
    10. // promise 中有定時器
    11. function timer(time){
    12. return new Promise(resolve => {
    13. setTimeout(()=>{
    14. resolve(`data-${time}`)
    15. }, time);
    16. });
    17. }
    18. // 同步迭代器返回 promise
    19. function *gen2(){
    20. yield timer(1000);
    21. yield timer(2000);
    22. yield timer(3000);
    23. }
    24. const g = gen2();
    25. for(let value of g){
    26. console.log(value); // 输出:Promise { } Promise { } Promise { }
    27. }
    28. // 异步生成器
    29. async function *gen3(){
    30. yield timer(1000);
    31. yield timer(2000);
    32. yield timer(3000);
    33. }
    34. async function test(){
    35. const g3 = gen3();
    36. // 三个异步生成器生成的 任务,这里不是同步执行的,是分别执行完,再从头开始执行的
    37. // 与普通的promise 普通的是并行执行的,分别会在第1、2、3秒输出结果
    38. const arr = [g3.next(), g3.next(), g3.next()];
    39. for await(const req of arr){
    40. console.log(req.value); // 第一秒的时候: data-1000 第三秒的时候:data-2000 第六秒的时候:data-3000
    41. }
    42. }
    43. test()

    16、ES11

    16.1、动态导入

    1. DOCTYPE html>
    2. 异步迭代

    16.2、模块化开发相关

    module.js

    1. export default {
    2. name: 666
    3. }
    4. export function test(){}

    统一管理模块

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

    16.3、globalThis

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

    17、ES12 及之后的

    17.1、逻辑运算符

    1. // &&=
    2. let a = 10
    3. a &&=20
    4. console.log(a) // 20
    5. let b = 0
    6. b &&=20
    7. console.log(b) // 0
    8. // ||=
    9. let c = 10
    10. c ||=20
    11. console.log(c) // 10
    12. let d = 0
    13. d ||=20
    14. console.log(d) // 20
    15. // ??=
    16. let e = 10
    17. e ??=20
    18. console.log(e) // 10
    19. let f = 0
    20. f ??=20
    21. console.log(f) // 0
    22. // 示例
    23. let user = null
    24. user ??=666
    25. console.log(user) // 666

    17.2、数值分隔符

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

    17.3、WeakSet

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <title>weakSettitle>
    7. head>
    8. <body>
    9. <script>
    10. /**
    11. * weakSet
    12. * 类似于set,但是成员都是弱引用(且不嗯呢该是基本类型,只能是复杂类型),即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,
    13. * 如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。
    14. * 只有add delete has三个方法
    15. */
    16. const ws = new WeakSet();
    17. let obj = {name: 111};
    18. let foo = {age: 18};
    19. ws.add(foo);
    20. ws.add(obj);
    21. console.log(ws.has(obj)); // true
    22. console.log(ws.has(foo)); // true
    23. console.log(ws); // WeakSet {Object {name: 111}, Object {age: 18}}
    24. // foo = null; // 标记没了,则会被清除,不会考虑ws 中的东西
    25. // console.log(ws.has(foo)); // false
    26. // console.log(ws); // WeakSet {Object {name: 111}}
    27. // 与set 对比的话
    28. /*
    29. 1. set 中的元素可以是基本类型,也可以是复杂类型,而WeakSet 中的元素只能是复杂类型
    30. 2. WeakSet 中的元素都是弱引用,而set 中的元素都是强引用
    31. 3. WeakSet 中的元素都是不可枚举的,而set 中的元素都是可枚举的
    32. 4. WeakSet 中的元素都是不可遍历的,而set 中的元素都是可遍历的
    33. */
    34. // 1. 基本类型
    35. let ws2 = new Set();
    36. let obj2 = {name: 111};
    37. let foo2 = {age: 18};
    38. ws2.add(foo2);
    39. ws2.add(obj2);
    40. console.log(ws2.has(obj2)); // true
    41. console.log(ws2.has(foo2)); // true
    42. console.log(ws2); // Set(2) {Object {name: 111}, Object {age: 18}}
    43. foo2 = null; // 标记没了,则会被清除,不会考虑ws 中的东西
    44. console.log(ws2.has(foo2)); // false
    45. console.log(ws2); // Set(1) {Object {name: 111}, Object {age: 18}} 引用还是在,就会出现问题
    46. script>
    47. body>
    48. html>

    17.4、weakMap

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <title>异步迭代title>
    7. head>
    8. <body>
    9. <script>
    10. /**
    11. * weakMap
    12. * 类似于map,但是key只能是对象,不能是其他类型
    13. * 只有get set delete has四个方法
    14. * 不能遍历、垃圾回收机制会自动回收
    15. * 应用场景:
    16. * 1、存储一些需要频繁访问的数据
    17. */
    18. const weakMap = new WeakMap();
    19. let obj = { name: 'zs' };
    20. weakMap.set(obj, 'value');
    21. console.log(weakMap.get(obj)); // value
    22. console.log(weakMap.has(obj)); // true
    23. console.log("有值", weakMap); // WeakMap { key:{ name: 'zs' }, value: 'value' }
    24. obj = null
    25. console.log("无值", weakMap); // WeakMap {} 如果是 Map 则这里会有值,就有可能会造成内存泄漏的情况
    26. script>
    27. body>
    28. html>

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

  • 相关阅读:
    石油化工行业商业供应链管理系统:大数据支撑,打造高质量可视化供应链
    工业场景全流程!机器学习开发并部署服务到云端 ⛵
    Java——基本数据类型
    【SA8295P 源码分析 (三)】97 - QNX AIS Camera 框架介绍 及 Camera 工作流程分析
    [UE]常见数学和插值
    TXT文本文件存储
    Python 逢七拍手小游戏2.0
    QSS 自定义QLineEdit
    干货 | 在Docker 上搭建持续集成平台 Jenkins
    主流分布式存储技术对比分析:GFS、HDFS、GlusterFS、Ceph、Swift
  • 原文地址:https://blog.csdn.net/weixin_44832362/article/details/139665974