者 | Loraine Lawson
译者 | 张卫滨
策划 | Tina
本文最初发表于The New Stack网站,由 InfoQ 中文站翻译分享。
在 2024 年,前端领域会有怎样的发展呢?因为没有人能够预见未来,所以 The New Stack 与来自 Angular、Next.js、React 和 Solid 的创建者和维护者讨论了他们 2024 年的计划。以下是前端开发者对未来一年的展望。
来自谷歌的 Angular DevRel 技术主管和经理Minko Gechev说,在过去的一年里,Angular 的两大成就是引入了基于Signals的细粒度反应性和可延迟视图。他告诉 The NewStack,新的一年将会在此基础上进一步关注细粒度的反应性,并使 Zone.js 成为可选的。
在 Angular 中,Zone 是一个执行上下文,它能够跨异步任务持续存在。在这个GitHub仓库中详细介绍了Zone,它有五个职责,包括拦截异步任务调度和包装回调以便于进行错误处理,以及跨异步操作的 zone 跟踪。Zone.js 可以创建跨异步操作而持久化存在的上下文,也可以为异步操作提供生命周期钩子。
Gechev 说,“我们正在探索为现有的项目实现可选的 Zone.js,开发人员可以通过重构现有的应用程序来利用这一特性”。“借助可选的 Zone.js,我们期待加载时间能够得以改善,并实现更快的初始渲染。对细粒度反应式的处理将提升到一个新的层次,使我们能够仅探测组件模板的部分变更。”
他说,这些特性将会带来更快的运行时。
在关于性能的另一个方面,Angular 正在考虑是否默认启用混合渲染。他补充说,选择避免混合渲染是可能实现的,因为这会增加托管需求和成本。
Gechev 说,“我们看到了 SSG(静态站点生成,static site generation)和 SSR(服务器端渲染,server-side rendering)的很多价值,而且在 v17 中奠定了坚实的基础,我们正在进行最后的润色工作,以便从一开始就实现这种体验。”
他补充到,另一个优先事项是完成Signals请求的评论(Request for Comment)。
开发人员还可以看到 Angular 文档的改进。根据对开发人员的调查,他们希望能有一个升级的学习体验,其中包括让 Angular.dev 成为该框架新的托管地。他补充说,开发人员还优先考虑了初始加载时间(混合渲染、部分填充和可选的 Zone.js 应该可以部分解决该问题)和组件编写,Angular 计划会进一步简化组件的编写。
Gechev 说,“我们致力于迭代式地交付特性,并随着时间的推移逐步增强它们”。“开发人员将能够从 2024 年的所有改进中受益,并在接下来的几年里获得更好的开发体验和性能。”
Next.js 在 2023 年引入了一个新的应用服务器,旨在支持 React 服务器组件(React Server Component,RSC)和Server Action。Vercel(该框架的监管者)的产品负责人 Lee Robinson 说,该框架会继续支持旧的服务器,并且其路由系统可以在两者实现互操作性。这种互操作性意味着可以继续花时间添加新的特性。
Robinson 说,“有些客户已经使用 Next.js 进行开发有五六年之久了,他们也会需要花费几年的时间来采用这些新特性。在这个过程中,我们希望他们的工作能够尽可能地顺畅。”
在新的一年中,Next.js 希望要解决很多问题,其中一个优先事项就是简化缓存。他说,从开发人员的体验来看,这可能会使其更加容易。
Robinson 说到,“通常情况下,生态系统中的许多开发人员必须引入一堆额外的包,或者学习如何使用其他的工具来进行数据抓取、缓存和重现校验”。“现在,Next.js 已经构建了很多这样的特性,而且非常强大,但是这也意味着需要学习更多的东西,我们得到的初步反馈是,‘这非常棒,也很强大,但是我们希望它能更简单一些’”。
Next.js 团队还将继续关注性能的改进,他将其称之为“我们的持续投资”。
他补充到,在新的一年里,这很可能会以新编译器的形式出现,它将加快在开发人员的机器上启动 Next.js 的速度。该编译器相关的工作已经进行了大约一年的时间,Vercel 一直在其内部产品和应用中使用它。他说,这个使用 Rust 编写的编译器即便在没有使用的缓存的情况下也比之前启用缓存的编译器更快。
Robinson 说,“距离推出这个功能已经近在咫尺了,甚至到了每个人都可以默认启用它的程度,而且它比现有基于 Webpack 的编译方案更快”。“开发人员总是希望他们的工具能够更快。他们对工具运行速度的追求永无止境。因此,很有意思的一件事是,工具的制造商,而不是工具的使用者在开始转向像 Rust 这样的底层工具,从而帮他们实现性能方面的最终胜利。”
他们的第三个目标是为未来十年的 Next.js 奠定基础。
他说,“我们对这个新的路由系统感到非常兴奋。我们相信这是未来的基础。但是,这也需要时间。人们会尝试使用,从而有特性方面的需求,并且希望能够看到实际的改变。我们将其视为未来五年至十年的长期投资。”
他补充说,一个“某天”可能会实现的目标是在 Next.js 中找到更好方式来处理内容,不过这应该不会新的一年中实现。
他补充说,“现在,它依然能够正常运行,你依然可以连接到任何你想要的内容源,但是会有一些潜在的方式能够简化开发人员的体验”。“这更像是一件锦上添花的事情,而不是必须要做的事情,这就是为什么我认为在 2024 年我们不会实现它,但我希望未来会为其做一些相关的工作。”
Meta 的 React 工程主管 Eli White 说,React 团队希望在新的一年里会有更多的框架采用 React 服务器组件(RSC,React Server Component)。
White 说,“对大多数人来讲,他们认为 RSC 是 React 领域的重要变化,从一个单纯的 UI 层,变成对如何架构应用程序的方式都能产生更大的影响,以获得最佳的用户和开发人员体验,特别是对于单页应用程序(SPA,single page application)方式表现不够好的应用程序。”
虽然他没有明确说明 2024 年的新动向,但是 White 表示他们将发布和分享 2023 年相关事项的更多进展。比如,在 React Advanced 会议上,团队向与会者展示了 React Forget,这是 React 的自动记忆编译器。White 说,有了React Forget之后,将意味着开发者不再需要使用useMemo和useCallback。
White 补充说,“在 React Native EU 会议上,我们分享了从 0.73 版本开始将 web 开发人员熟悉的 Chrome 开发工具引入 React Native。我们还初步展示了对 Static Hermes 的研究成果,这是针对 JavaScript 的原生编译器,它不仅有可能加快 React Native 应用程序的速度,而且会从根本上改变 JavaScript 的用途。”
Solid 创始人 Ryan Carniato 表示,在 2024 年,Solid 开发人员可以期待即将推出的SolidStart 1.0和 Solid.js 2.0。SolidStart 是一个元框架,这意味着它建立在框架 Solid.js 之上。他说,这类似于Svelte的SvelteKit。
SolidStart的文档是这样描述的:
“Web 应用程序通常包含很多组件,比如数据库、服务器、前端、打包器、数据抓取/变更、缓存和基础设施。编排这些组件很具挑战性,并且通常需要跨应用程序技术栈共享大量的状态和冗余逻辑。这就是 SolidStart 的用武之地,它是一个元框架,提供了一个将所有这些组件组合在一起的平台。”
由于 SolidStart 仍处于 beta 阶段,Carniato 有机会利用生态系统中已有的东西将其变得更好。
Carniato 说,“其中很重要的一点是,我们现在不再需要编写自己的部署适配器,而是可以使用 Nitro,它也支撑了 Nuxt 框架,这使得我们可以将其部署到所有的不同平台上。”
另外一个样例是任何 Solid 路由器都能在 SolidStart 中运行。
他说,“这意味着对路由器的底层部分进行了大量更新,这样它们才能一起运行,但最终结果令我非常高兴,因为我们小团队的志愿者需要维护的代码量要少得多,这给了开发人员很大的灵活性。”“他们不必被迫采用单一的解决方案,这对我来说非常重要,因为每个人都有自己的需求。正如我所言,如果你构建了正确的组件并且能够弄清楚构建基块(building block),那么人们可以做更多的事情。”
他说,最终的结果是由“可互换”的组件所组成的元框架,而不是具有很强的倾向性。Solid 团队一直在思考,在由越来越多的元框架决定开发人员能够使用什么的世界中,正确的基本元素所带来的影响。
他说,“对我来讲,最重要的一直是基本元素形成的构建基块,这是一个非常工程化的关注点,我认为这也是它与众不同的原因之一。”“我一直喜欢给别人选择的权力,并且我认为如果有正确的基本元素,正确的构建基块,就可以构建出正确的解决方案。”
他表示,Solid 2.0 应该会在 2024 年中后期发布。现在,他们正在实现如何处理异步系统的原型。
Carniato 说,“Solid 2.0 也将是一个非常重要的版本,因为我们正在重新审视反应式系统,并思考如何解决异步信号或异步系统的问题。”
他补充说,Solid 试图在控制和性能之间取得平衡。
他说,“在我们的社区里,有很多非常热情的人,非常有技术头脑的人,他们关注性能,关心控制。”“我们确实吸引了很多人,他们真的想控制自己建造的每一个组成部分。”
原文链接:https://www.infoq.cn/article/7ciYZE56w7KENEGOjfQY
者 | Adrien Joly
译者 | 张卫滨
策划 | 丁晓昀
有时候,JavaScript(甚至带有类型检查的 TypeScript)会因为其不可预测的特性和缺乏约定而遭到批评。对于那些知道 JavaScript 是为 web 浏览器设计的脚本语言的人来说,这就不足为奇了。
但是,现在它已经成为开发全栈 web 的首选语言,也是跨平台移动应用的热门方案。那么,当开发人员的 JavaScript/TypeScript 代码库开始老化,由此带来的复杂性痛苦地增长时,他们该采取什么行动才能最大限度地减少资源浪费并保持工作满意度呢?
本文将基于我 10 多年来编写 JavaScript 代码的经验和 5 年多拯救 JS/TS 项目的经历,向读者介绍如下内容:
在开发下一个特性时,每个警告、类型错误或非正常的测试都会让开发人员浪费时间、精力和专注度。
代码警告尤其令人讨厌,因为开发人员会习惯性地忽略它们,“只要一切按预期运行就好”。因此,它们会迅速累积,当我们遇到缺陷、事故或系统的意外行为时,就很难将其作为有用的线索。
类型错误就是一个很好的样例。当我们的用户遵循“快乐路径(happy path)”时,这些错误似乎无关紧要,因为软件似乎能够按照预期运行。所以,我们可能会使用@ts-ignore、any或类型断言来暂时忽略它们。但是,这样做的话,就意味着如果有一天用户选择不同的路径,就会面临运行时错误。
这样的话,开发人员就需要调查、重现和修复一个新的缺陷,而这个缺陷恰恰是他们几个月前允许走捷径所造成的。如果你的代码被各种警告和/或暂时忽略这些警告削弱了质量,那么找到这个捷径将耗费大量的时间。
当生产环境的数据库因“内存不足”错误而崩溃时,该警告可能会帮助开发人员找到崩溃的原因
警告和类型错误是查找缺陷和事故的线索。我们累积(或忽略)的警告和错误越多,开发人员就会花费越多的时间去调查。如果代码是他们很久以前编写的,那情况就会更糟糕了。
类型检查器认为缺少一个预期的属性。忽略这个错误将意味着要承担持久化不一致数据的风险,在几个月之后,你可能需要花费几天的时间来调查和解决这个问题
有许多静态代码分析工具可供使用,最常用的包括:
警告也可能来自其他工具:依赖安装器(如npm和yarn)、打包器(如webpack)、代码处理器(babel、scss)和执行环境(CI 运行器)。不要忽视它们!
如果遵循这些建议会让你的代码变得非常冗长和/或复杂(比如防御式代码),你可以需要对其进行重新设计。
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint:errors": "eslint . --quiet",
"lint:typescript": "tsc --noEmit --skipLibCheck",
"lint:jsdoc-typing": "tsc --noEmit --allowJs `find ./ -name '*.js' -name '*.d.ts'`"
},
复制代码
借助静态代码分析器和 npm 脚本,能够让开发人员轻松快速地探测有问题的代码
安装和配置静态代码分析工具是一个良好的开端,但这还不够。
要想取得持续的成功,要确保开发团队做到如下几点:
如下几种策略可能会提供帮助:
当某项职责没有人负责时,集体责任往往会被其他“优先事项”所取代(比如,本周多交付一个特性,但是代价是忽略一个警告)。
定期轮换角色,确保每个人都能参与其中并保持积极性。
现在,我们有了一支致力于保持代码库整洁的团队,我们相信用户很少会遇到编程错误。
但是,业务逻辑中的错误该怎么办呢?
例如,如果一个新添加的功能破坏了另一个功能该怎么办?如果开发人员从一开始就误解了该功能的预期行为,又该怎么办?如果这样的错误最终导致了严重的收入损失又该如何处理?
与编程错误类似,业务逻辑问题可能会在生产环境由用户发现,但我们更希望尽早发现它们。因此,定期测试软件非常重要,这个过程可以使用自动化和/或手动测试。
从业务角度看,测试有两个作用:
确保功能性测试(也称为“验收测试”)涵盖大多数关键业务特性,单元测试或集成测试涵盖大多数关键技术组件。此外,确保持续集成在任何测试失败时都能向开发人员提供可执行的反馈。
对于有些开发人员来说,将测试工作委托给其他人(如产品负责人或 QA 团队)是很有诱惑力的做法。在每个新特性完成后,进行一次这样的委托测试,以确保特性实现符合功能性需求,并进行协作迭代,这样做可能是合理的。
但是,委托他人进行回归检测并不是一个好主意,原因包括:
回归测试是一项痛苦且可能代价高昂的负担,尤其是需要不同角色(如产品负责人和开发人员)必须协作的情况下。从长远来看,回归测试自动化意味着可以节省大量的时间,而且开发人员具有编写自动化测试的技能,所以,开发人员首先要承担起检测回归的责任,而不必让其他角色参与进来,这符合他们的利益。
从最关键的业务特性开始。要找出这些特性,你可以问自己:“就收益和/或减少成本而言,在生产环境中可能发生的最糟糕的事情是什么?”
例如,电子商务网站的回答可能是如下的特性:
基于这些业务关键的用例,从它们开始编写端到端的自动化测试肯定就是非常有意义的。
在每次代码更新或添加到代码库之时,在将其部署到生产环境之前。
借助git hook,在每次提交时运行测试可能就足够了,因为它能可靠地运行,而且其持续时间不会导致开发人员编写更少的测试。
不管是否使用git hook,都要确保每次推送可用于生产环境的代码时,测试能在某处运行(例如,最好是在持续集成环境中)。
在持续集成环境中,每次提交都会运行代码检查和自动化测试。
需要优化的变量包括:
如果你的团队在编写自动化测试和/或可测试代码方面经验不足,那么可以从一些端到端测试开始。然后,逐步增加对范围更小的代码单元的测试。这样做可以激励开发人员编写易于测试的代码。例如,通过隔离责任、减少耦合和/或将业务逻辑写成纯函数。遵循依赖注入架构是实现这一目标的好方法。(参见六边形架构或简洁架构)
自动化测试(如本文所述)的目的是探测团队的功能性范围内的回归,而不是第三方的功能。基于这一点,在测试中 Mock 第三方是合理的。
也就是说:
探测自己的代码中的问题和第三方 API 中的问题并不遵循相同的生命周期:
你需要持续监控第三方提供商是否能够正常运行并达到预期效果。但是,第三方错误不一定能够在发生之时就探测到,因此最好是定期监控,而不是在开发人员每次推送代码变更的时候进行监控。
所以,需要搭建两个专门的流水线:
为了编写长期最有用、最健壮的测试,我建议遵循F.I.R.S.T.原则。确保开发人员不会滥用mock。
假设你的代码库已经或者将要开发数年的时间,那么随着时间的推移,它很可能会在代码风格和质量方面失去内聚力。更糟糕的是,由于技术债务、缺乏测试或意外复杂性的积累,某些组成部分的维护可能会变得很复杂。
在这种情况下,要像上文所建议的那样,在整个代码库中对代码实现一致的内聚预期可能会变得很复杂。不过,这也没有关系。
你不希望看到的是期望值降低到一个最低的平均水准。这样的话,你可以把代码划分为不同的范围,并为每个范围设置不同的期望水平。
例如,考虑一个即将为电子商务网站实现新特性的团队。他们希望这个新特性能够比代码库中的其他特性更健壮、更易于维护。为了实现这一点,他们在配置静态代码分析工具(如 ESLint 和 TypeScript)时采用比代码库的其他部分更严格的规则,并针对专门为该特性而创建的目录使用覆盖的方式启用更多的规则。通过这种方式,团队可以提高新代码的质量,而不必急于对代码库中“遗留”的部分进行现代化处理。
"rules": {
"prettier/prettier": "error",
"deprecation/deprecation": "warn"
},
"overrides": [
{
// Tolerate warnings on non critical issues from legacy JavaScript files
"files": ["*.js"],
"rules": {
"prefer-const": "warn",
"no-inner-declarations": ["warn", "functions"],
"@typescript-eslint/ban-ts-comment": "warn",
"@typescript-eslint/no-var-requires": "off"
}
},
{
// Enforce stricter rules on domain / business logic
"files": ["app/domain/**/*.js", "app/domain/**/*.ts"],
"extends": ["async", "async/node", "async/typescript"],
"rules": {
"prefer-const": "error",
"no-async-promise-executor": "error",
"no-await-in-loop": "error",
"no-promise-executor-return": "error",
"max-nested-callbacks": "error",
"no-return-await": "error",
"prefer-promise-reject-errors": "error",
"node/handle-callback-err": "error",
"node/no-callback-literal": "error",
"node/no-sync": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/promise-function-async": "error"
}
}
]
复制代码
通过配置覆盖,我们可以为不同的部分设置不同的 ESLint 规则
与之类似,如果要对整个代码库进行现代化改造,也要循序渐进。你可以创建一个具有更严格规则的专用目录,并逐渐将遗留代码迁移至该目录,同时修复代码的警告和类型错误。
有种方式是逐步将功能范围中陈旧的部分迁移到更好的设计中。例如,选择一个难以编写自动化测试的特性,并将它的实现迁移到六边形架构中,将业务/领域逻辑根据输入命令(即“API”)和副作用(即“SPI”)分离开来。通过编写自动化测试来指导迁移,并将新的实现放在具有更严格静态代码分析规则的专用目录中。
import { makeFeatures } = from './domain/features';
import { userCollection } from './infrastructure/mongodb/UserCollection';
import { ImageStorage } from './infrastructure/ImageStorage.js';
/** @type {import('./domain/api/Features').Features} Features*/
const features = makeFeatures({
userRepository: userCollection,
imageRepository: new ImageStorage(),
});
routes.post('/avatar', (request, response) => {
features
.setAvatar(request.session.userId, request.files[0])
.then(
() => response.json({ ok: true },
(error) => response.json({ ok: false })
);
});
复制代码
setAvatar特性经过了重新设计,由于采用了依赖反转,使其易于单独进行测试。下面是我们迁移另一项特性的过程,即播放列表删除
如果你决定遵循这一路径,如下是一些建议:
在迁移完每个限界上下文之后,你将会得到一个代码库,在代码库中 100%的代码都应按照更严格的规则进行检查。
尽管使用了静态分析工具来检测缺陷,使用了自动化测试来探测回归,但用户还是会在生产环境中发现问题。这是无法避免的。但是,有一种方法可以降低出现此类问题的概率,并缩短团队修复问题的时间:
简约版答案:因为DORA研究项目发现,大多数执行团队每天都在进行部署,或者每天部署多次。
详尽版答案:
在生产环境中出现意料之外的行为是可以的。在有些情况下,这甚至是一件好事。
当意料之外的行为给企业和/或开发团队带来巨大损失时(例如,网站中断,导致几个小时无法使用),开发人员应该采取措施防止类似的事件再次发生。
有多种方式可以探测生产环境中的问题:
无论是哪种情况,开发人员都需要以下信息:问题是什么、问题的具体表现(如错误信息)、如何重现问题(如环境+过程),以及用户的初衷和期望是什么。
但是,如何在最糟糕的情况下获得这些数据呢?这就是错误监控工具(如Sentry)的用武之地了。通过将它们注入到生产环境中运行的产品中,它们就能像探针一样检测运行时错误,并将它们汇总到已知错误的列表中,直到每个错误都被开发人员修复为止。此外,它们还会获取有关错误上下文的数据(如用户代理、所使用软件的版本、操作系统、确切的时间戳等),以帮助开发人员重现错误。
但令人遗憾的是,与静态代码分析器类似,这些工具并不能解决问题。因此,与警告和类型错误一样,要确保尽快处理每个错误。团队让错误累积得越多,使用这些工具的动力和效率就会越低。
此外,在使用这类监控工具时,请确保个人和/或机密数据不会从系统中泄露出去。
从战术上讲,有许多方法可供选择。你可以让一名开发人员负责修复生产环境的错误,并将其作为最优先的事项。这个角色可以定期轮换(比如每天),这样可以激励每个人都编写更健壮的代码。或者,也可以在每天的会议上将新错误单独分派给志愿开发人员。
不必慌张!当生产环境中发生事故时,都要遵守如下程序:
避免重蹈覆辙的关键在于上述程序的最后一步。
这也是经常被忽视的过程。大多数情况下,是因为没人觉得自己有责任这样做。很多时候,是因为产品负责人(或产品团队)向开发人员施压,要求他们优先完成开发计划中的特性,而不是保护现有代码和/或调整开发流程。有时,开发人员自己也会决定开发更多的特性,而不是避免再次犯错。
调查事故根本原因时的注意事项
在这个方面,“5 个为什么(5 WHY)”技巧是很有用的。例如:
在本例中,根本原因是整个网站都依赖于遗留的会话管理后端,这使得导航难以预测,有时还会导致生产环境崩溃。因此,除非团队修复传统的会话管理后端,否则类似的崩溃很可能很快就会在生产环境中再次发生。团队现在应该修复遗留的会话管理后端吗?也许不用。但是他们应该努力制定一个能够实现该目标的补救计划。
让一位开发人员负责确保尽快发现生产中的意外行为(如运行时错误、缺陷、事故……),尽快修复,并采取措施防止今后再次发生各类问题。
通过这种方式,开发人员能够感受到有能力在良好的条件下开展工作。例如,在生产过程中设置恰当的监控和日志,确保撰写有用的事后报告,并采取预防措施。
当信心达到良好水平时,逐步增加部署频率。
此时,开发人员就具备了编写高质量软件,并尽快发现缺陷的能力。这些缺陷最好是在设计或实现时发现,而不是在生产环境中。他们能够快速发现并修正生产环境的错误,不会重复犯同样的错误。他们对自己的代码和开发流程充满信心,因此每天都能在生产中实现改善。而且,他们在对软件功能化范围进行预期改善的同时,也会逐步改善代码库中最古老部分的设计和质量,使其保持健康、稳健并易于长期维护。
但是,令人遗憾的是,这种平衡很快就可能被瓦解。举例来说:
防止或解决这类情况可能会非常困难,因为这需要良好的领导力和/或软技能。
一个常见的错误是培养某种思维定式,即开发人员应该主要致力于实现优先的、计划好的和设计好的特性。
这样做是有问题的,因为:
下面是一些关于如何避免上述陷阱的建议:
JavaScript 语言及其不断变化的软件包和实践组成的生态系统会使代码库迅速变得难以维护。正如我们在本文所讨论的那样,无需从头重写所有的内容,也无需暂停新特性的开发,就可以避免由此造成的开发速度和/或代码质量的下降。
关于如何在 TypeScript 和 JavaScript 项目中应用这些推荐做法的更多实用建议,我建议你参考Yoni Goldberg的最佳实践列表。它们是为 Node.js(后端)项目编写的,但其中很多也适用于前端代码库。
原文链接:前端老手10年心得,JavaScript/TypeScript项目保养实用指南_架构/框架_InfoQ精选文章
了在TypeScript中封装一个获取当前年前后十年的方法,您可以定义一个函数,接受一个参数表示偏移量(正数表示未来年份,负数表示过去年份),并返回相应年份的数组。以下是一个实现示例:
function getYearsAroundCurrentDecade(offset: number): number[] {
const currentYear = new Date().getFullYear();
const startYear = Math.floor(currentYear / 10) * 10 + offset;
// Ensure we don't go beyond the year range supported by JavaScript's `Date` object.
const minYear = 0;
const maxYear = 9999;
if (startYear < minYear || startYear > maxYear) {
throw new Error(`The specified offset ${offset} leads to an out-of-range year.`);
}
// Generate an array of years spanning the decade.
const years = [];
for (let year = startYear; year < startYear + 10 && year <= maxYear; year++) {
years.push(year);
}
return years;
}
// Usage examples:
console.log(getYearsAroundCurrentDecade(0)); // [2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029]
console.log(getYearsAroundCurrentDecade(-1)); // [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
console.log(getYearsAroundCurrentDecade(1)); // [2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039]
这个函数首先获取当前年份,然后根据偏移量计算出目标十年的起始年份。它确保起始年份在JavaScript `Date`对象支持的合理范围内(通常是从公元0年到公元9999年),超出范围时抛出错误。接着,函数使用循环生成包含十年内所有年份的数组,并返回该数组。
通过调用此函数并传入不同的偏移量值(如`0`表示当前十年,`-1`表示前一个十年,`1`表示下一个十年),您可以轻松获取所需年份范围。
*请认真填写需求信息,我们会在24小时内与您取得联系。