当前位置: 首页 > article >正文

ES2021+新特性、常用函数

一、ES2021+新特性

ES2021

数字分隔符
 let num = 1234567 
 let num2 = 1_234_567
Promise.any
与 Promise.all 类似,Promise.any 也接受一个 Promise 的数组。当其中任何一个 Promise 完成(fullfill)时,就返回那个已经有完成值的 Promise。
如果所有的 Promise 都拒绝(reject),则返回一个拒绝的 Promise,该 Promise 的返回值是一个 AggregateError 对象。我们可以把 Promise.any 理解成 Promise.all 的相反操作。
  Promise.any(promises).then(
    (first) => {
      // 任何一个 Promise 完成了
    },
    (error) => {
      // 所有的 Promise 都拒绝了
    }
  );
逻辑符号简写
a ||= b;// 等同于 a = a || b  如果 a 为真则返回 a,如果 a 为假则返回 b
c &&= d;// 等同于 c = c && d  如果 a 为真,则返回 b , 如果 a 为假,则返回 a
e ??= f;// 等同于 e = e ?? f  如果 e 为 null或未定义,则返回 f;如果e为真,则返回e。

ES2022

类的构造新写法
旧:	
  class Car {
 		 constructor() {
   	 	this.color = 'blue';
    	this.age = 2;
  		}
		}
新:	
  class Car {
  	color = 'blue';
  	age = 2;
   	#firstName = 'Joseph';        // 私有变量 使用in来判断某个对象是否拥有某个私有属性
   	hasColor() {
   	 return #firstName in this;   //console.log(car.hasColor()); // true
  	}
	}
顶层await
 //旧:
	function timeout(ms) {
  	return new Promise((resolve) => {
   	 setTimeout(resolve, ms);
  	});
	}

	async function asyncPrint(value, ms) {
 	 await timeout(ms);
  	console.log(value);
	}

	asyncPrint('hello world', 50);

//新:
	function setTimeoutAsync(timeout) {
 	 return new Promise((resolve) => {
    setTimeout(() => {
     	 resolve();
    	}, timeout);
   })
 }
	await setTimeoutAsync(3000);
字符串、数组的at()方法
//数组
	const arr = ['a', 'b', 'c', 'd'];
// 倒数第一个元素
	console.log(arr.at(-1)); // d
	console.log(arr.at(-2)); // c
//字符串
	const str = 'Coding Beauty';
	console.log(str.at(-1)); // y
	console.log(str.at(-2)); // t
//TypedArray对象
	const typedArray = new Uint8Array([16, 32, 48, 64]);
	console.log(typedArray.at(-1)); // 64
	console.log(typedArray.at(-2)); // 48
正则表达式匹配字符串的时候支持返回开始和结束索引
const str = 'sun and moon';
	const regex = /and/d;                   //给正则表达式添加一个d的标记;返回匹配到的子字符串的起始位置还返回其结束位置
	const matchObj = regex.exec(str);
/**
[
  'and',
  index: 4,
  input: 'sun and moon',
  groups: undefined,
  indices: [ [ 4, 7 ], groups: undefined ]
]
 */
	console.log(matchObj);
Object.hasOwn()方法,检查某个对象自身是否拥有某个属性
const obj = Object.create(null);
obj.color = 'green';
obj.age = 2;
obj.hasOwnProperty = () => false;

console.log(Object.hasOwn(obj, 'color')); // true
console.log(Object.hasOwn(obj, 'name'));  // false  基本等价于obj.hasOwnProperty('name')
数组支持逆序查找findLast()和findLastIndex()
const nums = [7, 14, 3, 8, 10, 9];

const lastEven = nums.findLast((num) => num % 2 === 0);
const lastEvenIndex = nums.findLastIndex((num) => num % 2 === 0);

console.log(lastEven); // 10
console.log(lastEvenIndex); // 4

ES2023

数组的新方法
Array.prototype.toReversed()                                // 该方法返回一个新数组,新数组的元素顺序与原数组相反。
Array.prototype.toSorted(compareFn)                         // 该方法返回一个新数组,新数组的元素是原数组元素的排序结果。
Array.prototype.toSpliced(start, deleteCount, ...items)     // 该方法返回一个新数组,新数组删除了原数组从指定位置开始的指定数量的元素。
Array.prototype.with(index, value)                          // 该方法返回一个新数组,新数组在指定索引位置的元素被替换为指定值。
Array.prototype.findLast()                                  // 从数组中获取匹配元素的最后一个实例,如果找不到匹配元素,则返回 undefined。
Hashbang 语法
#!/usr/bin/env node
// in the Script Goal
'use strict';
console.log(2*3);

#!/usr/bin/env node
// in the Module Goal
export {};
console.log(2*2);
Symbol 作为 WeakMap 的键
在这之前,WeakMap仅允许对象作为键值,新特性更容易创建和共享key。

var map = new WeakMap(); // 创建一个弱映射
function useSymbol(symbol){
    doSomethingWith(symbol);
    var called = map.get(symbol) || 0

上面的例子允许从外部调用者调用计数器,并在不再有引用时释放映射条目。
代码本身无法知道何时不再需要引用,如果使用普通的 Map,将会导致内存泄漏。
这是因为即使在调用它的客户端不再需要引用时,代码仍然会保留对该引用的持有。
在这种情况下使用 WeakMap,可以确保垃圾回收在不再存在对键符号的引用时删除映射条目。

ES2024

Promise.withResolvers()
// Promise.withResolvers() 允许创建一个新的 Promise,并同时获得 resolve 和 reject 函数。

// old
let resolve, reject;  
const promise = new Promise((res, rej) => {  
    resolve = res;  
    reject = rej;  
});

// new 
const { promise, resolve, reject } = Promise.withResolvers();  
  
// 在这里可以使用 resolve 和 reject 函数  
setTimeout(() => resolve('成功!'), 8000);  
  
promise.then(value => {  
    console.log(value); // 输出: 成功!  
});
数组分组

Object.groupBy()

// Object.groupBy返回一个普通对象
const fruits = [
    { name: "Apple", color: "red" },
    { name: "Banana", color: "yellow" },
    { name: "Cherry", color: "red" },
    { name: "Lemon", color: "yellow" },
    { name: "Grape", color: "purple" },
];

const fruitsByColor = Object.groupBy(fruits, (fruit) => fruit.color)
// 注意,使用Object.groupBy方法返回一个没有原型(即没有继承任何属性和方法)的对象。这意味着该对象不会继承Object.prototype上的任何属性或方法。

Map.groupBy()

// Map.groupBy返回一个 Map 对象
const fruits = [
    { name: "Apple", color: "red" },
    { name: "Banana", color: "yellow" },
    { name: "Cherry", color: "red" },
    { name: "Lemon", color: "yellow" },
    { name: "Grape", color: "purple" },
];

const fruitsByColor = Map.groupBy(fruits, (fruit) => fruits.color); // 返回map对象

二、常用函数部分

1、自定义一个缓存函数
// Map.groupBy返回一个 Map 对象
const fruits = [
    { name: "Apple", color: "red" },
    { name: "Banana", color: "yellow" },
    { name: "Cherry", color: "red" },
    { name: "Lemon", color: "yellow" },
    { name: "Grape", color: "purple" },
];

const fruitsByColor = Map.groupBy(fruits, (fruit) => fruits.color); // 返回map对象
2、检查对象是否为空
即使对象为空,每次检查对象是否等于 {} 也会返回 false。
const isEmpty = obj => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object
3、检查设备上的触摸支持
const touchSupported = () => ('ontouchstart' in window || DocumentTouch && document instanceof DocumentTouch)
4、重定向到另一个 URL
const redirect = url => location.href = url
5、检测某个元素是否聚焦
const hasFocus = el => el === document.activeElement
6、获取所有 cookie 并转为对象
const getCookies = () => document.cookie
  .split(';')
  .map(item => item.split('='))
  .reduce((acc, [k, v]) => (acc[k.trim().replace('"', '')] =v) && acc, {})
7、清除所有 cookie
const clearCookies = () => document.cookie
  .split(';')
  .forEach(c => document.cookie = c.splace(/^+/, '')
          .replace(/=.*/,`=;expires=${new Date().toUTCString()};path=/`))
  )
8、从对象中删除值为 null 和 undefined 的属性
const removeNullAndUndefined = (obj) => 
  Object.entries(obj).reduce((a, [k, v]) => (v == null ? a : ((a[k] = v), a)), {});
9、js下载图片
const imgUrl = "";// 图片链接
    const a = document.createElement('a');
    // 这里是将url转成blob地址,
    fetch(imgUrl)  // 跨域时会报错
      .then(res => res.blob())
      .then(blob => { // 将链接地址字符内容转变成blob地址
        a.href = URL.createObjectURL(blob);
        a.download ='追溯二维码.jpg'; // 下载文件的名字
        document.body.appendChild(a);
        a.click();
        //在资源下载完成后 清除 占用的缓存资源
        window.URL.revokeObjectURL(a.href);
        document.body.removeChild(a);
      })
10、瀑布流布局
const waterFall = () => {
  	//瀑布流核心代码
    let img = $(".img-item");//获取图片集合
    let imgWidth = $(".img-item").width();//当前图片宽度
    let boxWidth = $(".img-box").width();//瀑布流布局框宽度
    let cols = parseInt(boxWidth / imgWidth);//求出列数
    let heightArr = [];//创建高度数组,用于存储各行当前高度
    // 遍历图片集合
    $.each(img, function (index, item) {
        let imgHeight = $(item).height();//取出对应图片的高度
        if (index < cols) {//判断是不是第一行,第一行索引0~cols-1,
            //第一行直接存入高度数组
            heightArr[index] = imgHeight;
        } else {
            //非第一行操作,将此次图片定位到高度最低的一列
            //获取高度数组中的最小值,即所有列中最小的一列,是此次图片定位的起始高度,即top
            let minBoxHeight = Math.min(...heightArr);
            //获取最小高度对应的列索引,$.inArray()用于查找对应数组中指定值的索引。(未匹配成功的话,返回-1)
            //从而可以判断出此次图片定位的起始left
            let minBoxIndex = $.inArray(minBoxHeight, heightArr)
            //图片定位插入对应位置
            $(item).css({
                position: 'absolute',
                //加10是因为css设置了右外边距
                left: minBoxIndex * (imgWidth + 10) + 'px',
                //加6是为了让间距相同,视觉舒适
                top: minBoxHeight + 6 + 'px'
            })
            //高度追加,存入高度数组
            heightArr[minBoxIndex] += imgHeight + 6;
        }
    })
    //获取每次执行完的最大高度,用于设置瀑布流盒子高度
    //因为瀑布流图片设置绝对定位而使,盒子高度塌陷
    //最后执行完就是整个瀑布流盒子的高度
    let maxBoxHeight = Math.max(...heightArr);
    $(".img-box").css("height", maxBoxHeight);
}
11、分散节点转树
// 子节点遍历成树
export function formatToTree(array: Array<any>, pid?: any) {
  return array
    .filter((item) =>
      // 如果没有父id(第一次递归的时候)将所有父级查询出来
      // 这里认为 item.parentId === 0 顶层 id
      pid === undefined ? item.parentId === 0 : item.parentId === pid
    )
    .map((item) => {
      // 通过父节点ID查询所有子节点
      item.children = formatToTree(array, item.id);
      return item;
    });
}
12、统计一个对象中所有的数据类型
function countDataTypes(obj) {
  const types = {};

  function getType(value) {
    if (Array.isArray(value)) {
      return "array";
    } else if (value instanceof Date) {
      return "date";
    } else if (value === null) {
      return "null";
    } else {
      return typeof value;
    }
  }

  function countTypes(obj) {
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const type = getType(obj[key]);
        if (types[type]) {
          types[type]++;
        } else {
          types[type] = 1;
        }
        if (type === "object") {
          countTypes(obj[key]);
        }
      }
    }
  }

  countTypes(obj);
  return types;
}

// 测试用例:
const obj = {
  name: "John",
  age: 30,
  hobbies: ["reading", "coding"],
  address: {
    street: "123 Main St.",
    city: "Anytown",
    state: "CA"
  },
  favoriteColor: null,
  birthDate: new Date()
};

// 结果
{
  string: 1,
  number: 1,
  array: 1,
  object: 2,
  boolean: 0,
  undefined: 0,
  function: 0,
  symbol: 0,
  bigint: 0,
  null: 1,
  date: 1
}


http://www.kler.cn/a/525326.html

相关文章:

  • 【重生之我在学习C语言指针详解】
  • ping命令详解Type 8和0 或者Type 3
  • JavaScript
  • 基于Springboot的智能学习平台系统【附源码】
  • Baklib揭示内容中台与人工智能技术的创新协同效应
  • Kotlin开发(六):Kotlin 数据类,密封类与枚举类
  • 【Qt】06-对话框
  • 人口增长(信息学奥赛一本通-1070)
  • sudoers文件修改格式错误恢复
  • 《机器学习数学基础》补充资料:贝叶斯分类器
  • R语言统计分析——ggplot2绘图3——分组
  • 18.Word:数据库培训课程❗【34】
  • 无心剑七绝《经纬岁华》
  • llama.cpp LLM_ARCH_DEEPSEEK and LLM_ARCH_DEEPSEEK2
  • Tailwind CSS - Tailwind CSS 引入(安装、初始化、配置、引入、构建、使用 Tailwind CSS)
  • DeepSeek-R1:通过强化学习激励大型语言模型(LLMs)的推理能力
  • 代码随想录算法训练营第34天| 动态规划:01背包理论基础(二维和一维)、416. 分割等和子集
  • 【实践案例】使用Dify构建企业知识库
  • 探索Linux中的进程控制:从启动到退出的背后原理
  • 使用 Iptables 实现网络安全策略:从入门到精通
  • Python 梯度下降法(一):Gradient Descent
  • 10.8 FileSystemWatcher(文件监视)组件
  • k均值聚类将数据分成多个簇
  • 高级编码参数
  • 【Attention】KV Cache
  • TypeScript 学习 -类型 - 10