百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

2025 年每个 JavaScript 开发者都应该了解的功能

myzbx 2025-06-30 18:48 25 浏览

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。

1.Iterator helpers

开发者经常会对同一个数组执行多次链式转换,例如:

const arr = [];
arr
  .slice(10, 20)
  .filter((el) => el < 10)
  .map((el) => el + 5);

这种方式非常低效,因为每次转换都需要分配一个新数组。JS 引入了迭代器方法,其工作原理与常规数组转换类似。不同之处在于其不会创建临时数组,而是创建新的迭代器,这些迭代器会在其他迭代器上进行迭代。

  • Iterator.prototype.drop():返回一个新的 Iterator Helper 对象,该对象会跳过此迭代器开头指定数量的元素,其作用大致与常规数组的 Array.prototype.slice(n) 相同
  • Iterator.prototype.take():返回一个新的 Iterator Helper 对象,该对象从此迭代器的开头获取指定数量的元素,其作用与常规数组的 Array.prototype.slice(0, n) 相同
  • Iterator.prototype.some():类似于 Array.prototype.some(),其测试迭代器生成的元素是否至少有一个通过了所提供函数实现的测试元素
  • Iterator.prototype.every():类似于 Array.prototype.every(),其测试迭代器生成的所有元素是否都通过了开发者所提供函数的测试
  • Iterator.prototype.filter():类似于 Array.prototype.filter(),其返回一个基于筛选值的迭代器
  • Iterator.prototype.find():类似于 Array.prototype.find(),其返回迭代器生成的第一个满足所提供测试函数的元素,否则返回 undefined
function* fibonacci() {
  let current = 1;
  let next = 1;
  while (true) {
    yield current;
    [current, next] = [next, current + next];
  }
}
const isEven = (x) => x % 2 === 0;
console.log(fibonacci().find(isEven));
// 输出 2
const isNegative = (x) => x < 0;
console.log(fibonacci().take(10).find(isNegative));
// undefined
console.log(fibonacci().find(isNegative));
// Never completes
  • Iterator.prototype.flatMap():类似于 Array.prototype.flatMap(),其返回一个基于扁平化值的迭代器
// 展平可迭代对象
const map1 = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3],
]);
const map2 = new Map([
  ["d", 4],
  ["e", 5],
  ["f", 6],
]);
const merged = new Map([map1, map2].values().flatMap((x) => x));
console.log(merged.get("a"));
// 1
console.log(merged.get("e"));
// 5

该方法可以避免创建任何 map 内容的临时副本。但需要注意的是,数组 [map1, map2] 必须先通过. values() 转换为迭代器,因为 Array.prototype.flatMap() 只能展平数组,而不能展平可迭代对象。

  • Iterator.prototype.forEach():类似于 Array.prototype.forEach(),其对迭代器生成的每个元素执行一次提供的函数
  • Iterator.prototype.map():类似于 Array.prototype.map(),其返回一个由映射函数转换后的值的迭代器
  • Iterator.prototype.reduce():类似于 Array.prototype.reduce(),其对迭代器生成的每个元素执行用户提供的 reducer 回调函数,并传入前一个元素计算的返回值
// 该示例创建迭代器,该迭代器产生斐波那契数列中的项,然后对前十个项求和
function* fibonacci() {
  let current = 1;
  let next = 1;
  while (true) {
    yield current;
    [current, next] = [next, current + next];
  }
}
console.log(
  fibonacci()
    .take(10)
    .reduce((a, b) => a + b),
);
// 输出 143
  • Iterator.prototype.toArray():使用填充的生成值创建一个数组

创建可迭代对象的常用方法是通过静态方法 Iterator.from() 以及 Array、NodeList、Set 和许多其他容器的 values() 方法。因此,上面转换链示例的更节省内存的版本是:

const arr = [];
arr
  .values()
  .drop(10)
  .take(10)
  .filter((el) => el < 10)
  .map((el) => el + 5)
  .toArray();

需要注意的是,这是一个相对较新的功能,最后一个开始支持此功能的主流浏览器是 Safari,其从 2025 年 3 月 31 日才开始支持。

2. 数组的 at() 方法

Array.prototype.at() 是访问第 n 个元素的另一种方法,其还支持负索引,即从最后一个元素开始计数。

例如,[10,20,30].at(-1) 将返回 30,[10,20,30].at(-2) 将返回 20 等等。这种负索引使得访问最后一个元素变得非常容易。在此之前,开发者则必须编写丑陋的样板代码 arr[arr.length - 1]。

3.Promise.withResolvers()

在异步调用场景,开发者经常会编写如下代码:

let resolve, reject;
const promise = new Promise((resolver, rejector) => {
  resolve = resolver;
  reject = rejector;
});
// 在特定场景下调用 resolve 或者 reject 方法

但是,借助于最新的 Promise.withResolvers(),开发者可以轻松实现同样的功能。

const {promise, resolve, reject} = Promise.withResolvers();

Promise.withResolvers() 静态方法返回一个对象,其中包含一个新的 Promise 对象和两个用于 resolve 或 reject 的函数,对应于传递给 Promise() 构造函数执行器的两个参数。

4.String.prototype.replace() / String.prototype.replaceAll() 回调

这是个老生常谈的问题,很多开发者不知道 String.prototype.replace() 或
String.prototype.replaceAll() 的第二个参数可以传入回调函数而不仅仅是字符串。例如:

let counter = 0;
console.log(
  "NUMBER, NUMBER, NUMBER".replaceAll(
    "NUMBER",
    (match) => match + "=" + ++counter
  )
); // NUMBER=1, NUMBER=2, NUMBER=3

replace() 和 replaceAll() 是一个非常强大的功能,其允许一次性完成多次替换。而且,从性能和内存角度来看都非常高效。

5. 交换变量的最新方法

很多开发者经常使用下面的方式来交换变量:

let a = 1,
  b = 2;
console.log(a, b);
// 当前输出 1, 2
const temp = a;
a = b;
b = temp;
console.log(a, b);
// 交换后的输出 2, 1

现在 JavaScript 引擎提供了更加简单的方式来实现同样的功能:

let a = 1,
  b = 2;
console.log(a, b);
// 交换前 1, 2
[a, b] = [b, a];
console.log(a, b);
// 交换后 2, 1

6. 结构化克隆 structuredClone()

大部分浏览器都已经支持 structuredClone() API,其可以深度复制大多数常规对象从而替换 JSON.stringify() 和 JSON.parse() 进行深度复制的功能。因为后者在很多场景可能并不符合预期:

  • JSON.stringify() 不支持某些值,例如: NaN 或 undefined,这些值会被跳过或转换为 null。同时,对于某些数据类型,例如: BigInt,该方法甚至会抛出异常。
  • JSON.stringify() 无法处理包含循环引用的对象:
const obj = {};
obj.selfReference = obj;
console.log(JSON.stringify(obj));
// 直接抛出异常
  • 对于较大的对象来说,该方法效率不高且浪费大量内存

因此总体来看,开发者应尽可能优先使用 structuredClone(),其还会循环引用对象。

const obj = {};
obj.selReference = obj;
const clonedObj = structuredClone(obj);
console.log(obj === clonedObj);
// 输出 false
console.log(clonedObj.selReference === clonedObj);
// 注意:输出 true

7.Tagged templates

大多数开发者都熟悉模板字面量 "`",但很多人并不知道标记模板,标记模板允许开发者使用函数解析模板字面量。标记函数的第一个参数包含一个字符串值数组,其余参数与表达式相关。当想对插值,甚至整个字符串,进行一些自动转换时,标记模板非常有用。

`string text`

`string text line 1
 string text line 2`

`string text ${expression} string text`

tagFunction`string text ${expression} string text`

例如,下面代码示例会在进行插值时自动转义 HTML 文本:

function escapeHtml(strings, ...arguments) {
  const div = document.createElement("div");
  let output = strings[0];
  for (let i = 0; i < arguments.length; ++i) {
    div.innerText = arguments[i];
    output += div.innerHTML;
    output += strings[i + 1];
  }
  return output;
}
console.log(escapeHtml`<br> ${"<br>"}`);
// 输出结果 <br> <br>

8.WeakMap / WeakSet

除了 Map 和 Set 之外,JavaScript 还支持 WeakMap 和 WeakSet。

WeakMap 和 WeakSet 与 Map 和 Set 类似,不同之处在于其不允许将原始值作为键,并且不提供迭代器。这样做的原因是,当指向某个键的所有引用丢失时,该键以及可能关联的值必须能够从 Map/Set 中释放并被垃圾回收。

const set = new WeakSet();
const map = new WeakMap();
{
  const key1 = new Date();
  const key2 = new Date();
  console.log(set.has(key1));
  // false
  set.add(key1);
  console.log(set.has(key1));
  // true
  console.log(map.get(key2));
  // undefined
  map.set(key2, 10);
  console.log(map.get(key2));
  // 10
}
// 注意:此处丢失了对 key1 和 key2 的引用,因此键和值会将被垃圾收集

因此,如果开发者希望将某事物与某个对象关联而不产生副作用,可以考虑使用 WeakMap 或 WeakSet。

9.Set 操作

最近,JavaScript 增加了对 Set 对象的布尔运算支持。

Set.prototype.difference()

集合差运算:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
console.log(set1.difference(set2));
// 输出 Set(2) {1, 2}

Set.prototype.intersection()

执行集合交运算:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
console.log(set1.intersection(set2));
// 输出 Set(2) {3, 4}

Set.prototype.union()

执行集合并操作:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
console.log(set1.union(set2));
// 输出 Set(6) {1, 2, 3, 4, 5, 6}

Set.prototype.symmetricDifference()

除去两个集合的公共元素:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
console.log(set1.symmetricDifference(set2));
// Set(4) {1, 2, 5, 6}

Set.prototype.isDisjointFrom()

返回一个布尔值,指示该集合与给定集合没有共同元素:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
const set3 = new Set([5, 6]);
console.log(set1.isDisjointFrom(set2));
// 输出 false
console.log(set1.isDisjointFrom(set3));
// 输出 true

Set.prototype.isSubsetOf()

返回一个布尔值,指示该集合的所有元素是否都在给定集合中:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
const set3 = new Set([5, 6]);
console.log(set1.isSubsetOf(set2));
// 输出 false
console.log(set3.isSubsetOf(set2));
// 输出  true

Set.prototype.isSupersetOf()

返回一个布尔值,指示给定集合的所有元素都在此集合中:

const set1 = new Set([1, 2, 3, 4]);
const set2 = new Set([3, 4, 5, 6]);
const set3 = new Set([5, 6]);
console.log(set2.isSupersetOf(set1));
// 输出 false
console.log(set2.isSupersetOf(set3));
// 输出 true

参考资料

https://waspdev.com/articles

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/flatMap

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

https://medium.com/@emre.deniz/es2025-the-evolution-of-javascript-93d9f6fd5f5b

https://blog.bitsrc.io/javascript-iterables-vs-iterators-009162379a15?gi=7c4c7a926564

https://www.youtube.com/watch?v=8p9lPsui7Co

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 &quot;小贱贱&quot;韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...