在 javascript 中使用相邻参数作为函数的默认值

更多好文,欢迎关注公众号Geek技术前线

默认参数值在JavaScript中已经存在一段时间了。但其实可以将前面的相邻参数作为默认值本身。

JavaScript自ES2015以来就支持默认参数值,但我们可能不知道的是,我们可以将之前的相邻参数作为默认值

function myFunc(arg1, arg2 = arg1) {console.log(arg1, arg2);
}myFunc("arg1!");
// "arg1!" "arg1!"

MDN甚至对此进行了说明展示了这个特性如何帮助处理一些不寻常的函数签名。

一个场景

假设我们有一个OptimizedImage类。向其构造函数提供一个图像URL,我们可以获取一个新优化的图像缓冲区或一个缓存版本。

class OptimizedImage {constructor(imageUrl: string,cacheService = new CacheService(),optimizeService = new OptimizeService()) {this.imageUrl = imageUrl;this.cacheService = cacheService;this.optimizeService = optimizeService;}async get() {const cached = this.cacheService.get(this.imageUrl);// 返回之前优化过的图像。if (cached) return cached;const optimizedImage = await this.optimizeService.optimize(this.imageUrl);// 将优化后的图像缓存以备下次使用。return this.cacheService.put(this.imageUrl, optimizedImage);}
}const instance = new OptimizedImage('https://macarthur.me/me.jpg');
const imgBuffer = await instance.get();

在生产中使用的唯一构造函数参数是imageUrl,但注入CacheServiceOptimizeService使得使用模拟进行单元测试变得更加容易。

import { it, expect, vi } from "vitest";
import { OptimizedImage } from "./main";it("returns freshly optimized image", async function () {const fakeImageBuffer = new ArrayBuffer("image!");const mockCacheService = {get: (url) => null,put: vi.fn().mockResolvedValue(fakeImageBuffer),};const mockOptimizeService = {optimize: (url) => fakeImageBuffer,};const optimizedImage = new OptimizedImage("https://test.jpg",mockCacheService,mockOptimizeService);const result = await optimizedImage.get();expect(result).toEqual(fakeImageBuffer);expect(mockCacheService.put).toHaveBeenCalledWith("https://test.jpg", "optimized image");
});

更复杂的情况

在这个例子中,这两个服务类仅在特定方法被调用时使用 imageUrl。但想象一下,如果它们需要在自己的构造函数中传入这个参数,我们可能会想把实例化过程放入 OptimizedImage 的构造函数中

class OptimizedImage {constructor(imageUrl: string) {this.imageUrl = imageUrl;this.cacheService = new CacheService(imageUrl);this.optimizeService = new OptimizeService(imageUrl);}}

这样是可行的,但现在 OptimizedImage 完全负责服务的实例化,测试也变得更加麻烦。传入服务实例的模拟对象并不容易。

我们可以通过传入模拟类定义来解决这个问题,但这就需要为这些类创建带有自己构造函数的模拟版本,使得测试变得更加繁琐。幸运的是,还有另一种选择:在其余参数列表中使用 imageUrl 参数。

共享相邻参数

它的实现方式如下:

export class OptimizedImage {constructor(imageUrl: string,// 在两个依赖中使用相同的 `imageUrl`。cacheService = new CacheService(imageUrl),optimizeService = new OptimizeService(imageUrl)) {this.cacheService = cacheService;this.optimizeService = optimizeService;}async get() {const cached = this.cacheService.get();// 返回之前优化过的图像。if (cached) return cached;const optimizedImage = await this.optimizeService.optimize();// 将优化后的图像缓存以备下次使用。return this.cacheService.put(optimizedImage);}
}

通过这种设置,我们能够像之前一样轻松地模拟这些实例,并且类的其余部分甚至不需要保留 imageUrl 的实例。实例化过程当然仍然很简单:

const instance = new OptimizedImage("https://macarthur.me/me.jpg");const img = await instance.get();

同样的测试方法也依然适用:

import { it, expect, vi } from "vitest";
import { OptimizedImage } from "./main";it("returns freshly optimized image", async function () {const mockCacheService = {get: () => null,put: vi.fn().mockResolvedValue("optimized image"),};const mockOptimizeService = {optimize: () => "optimized image",};const optimizedImage = new OptimizedImage("https://test.jpg",mockCacheService,mockOptimizeService);const result = await optimizedImage.get();expect(result).toEqual("optimized image");expect(mockCacheService.put).toHaveBeenCalledWith("optimized image");
});

其他用例

考虑使用 .reduce() 计算一个数字数组的总和:

const numbers = [1, 2, 3, 4, 5];const total = numbers.reduce((acc, value) => {return acc + value;
});console.log(total); // 15

这个过程的“业务逻辑”在函数体内。但我们也可以将其作为默认参数放入函数签名中,这样函数体只需返回结果即可。

const total = numbers.reduce((acc, value, _index, _array, result = acc + value) => {return result;
});

我们还可以使用隐式 return 让代码看起来更炫酷:

const total = numbers.reduce((acc, value, _index, _array, result = acc + value) => result);

参考 https://macarthur.me/posts/sibling-parameters/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/56670.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(AtCoder Beginner Contest 375) 题解(下)

一、题解 第 E 题 3 Team Division 一眼看像背包,观察数据范围,合法的总能力值 ≤ 500 \le 500 ≤500,那么我们可以设计一个背包DP: int dp[110][510][510]; //dp[i][j][k] 表示前 i 个人,分给第一组的能力值是 j&…

微服务架构 --- 使用Seata处理分布式事务

目录 一.Seata 是什么? 1.Seata的核心架构: 2. Seata的分布式事务处理流程: 二.Seata的基本使用: 1.环境准备: 2.引入依赖: 3.加入配置来使用Seata: (1)首先在nacos上添加一…

免费版视频压缩软件:让视频处理更便捷

现在不少人已经习惯通过视频来记录生活、传播信息和进行娱乐的重要方式。但是由于设备大家现在录制的文件都会比较大,这时候就比较需要一些缩小视频的工具了。今天我们一起来探讨视频压缩软件免费版来为我们带来的生动世界。 1.Foxit视频压缩大师 链接直达&#x…

ESP32移植Openharmony外设篇(1)MQ-2烟雾传感器

外设篇 实验箱介绍 旗舰版实验箱由2部分组成:鸿蒙外设模块(支持同时8个工作)、鸿蒙平板。 其中,鸿蒙平板默认采用RK3566方案。 OpenHarmony外设模块采用底板传感器拓展板方式,底板默认采用ESP32方案,也…

青少年编程能力等级测评CPA C++一级试卷(1)

青少年编程能力等级测评CPA C一级试卷(1) 一、单项选择题(共20题,每题3.5分,共70分) CP1_1_1.在C中,下列变量名正确的是( )。 A.$123 B&#…

Redis 的安装与部署(图文)

前言 Redis 暂不支持Windows 系统,官网上只能下载Linux 环境的安装包。但是启用WSL2 就可以在Windows 上运行Linux 二进制文件。[要使此方法工作,需要运行Windows 10 2004版及更高版本或Windows 11]。本文在CentOS Linux 系统上安装最新版Redis&#xf…

【C++】unordered_set、unordered_map超详细封装过程,处理底层细节

🚀个人主页:小羊 🚀所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言1、数据泛型2、迭代器2.1 重载2.2 begin、end2.3 const迭代器2.4 unordered_map中[]重载 3、特殊类型 总结 前…

如何设计开发RTSP直播播放器?

技术背景 我们在对接RTSP直播播放器相关技术诉求的时候,好多开发者,除了选用成熟的RTSP播放器外,还想知其然知其所以然,对RTSP播放器的整体开发有个基础的了解,方便方案之作和技术延伸。本文抛砖引玉,做个…

Unity 实战案例全解析 实现时间停止效果+世界变灰

画面里运动的那个小玩意这么写 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Partol : MonoBehaviour {public Transform pos1;public Transform pos2;public float speed;private Transform target;void Start() {target p…

前端开发攻略---取消已经发出但是还未响应的网络请求

目录 注意&#xff1a; 1、Axios实现 2、Fetch实现 3、XHR实现 注意&#xff1a; 当请求被取消时&#xff0c;只会本地停止处理此次请求&#xff0c;服务器仍然可能已经接收到了并处理了该请求。开发时应当及时和后端进行友好沟通。 1、Axios实现 <!DOCTYPE html> &…

性能测试工具JMeter

本次使用的博客系统的url&#xff1a; http://8.137.19.140:9090/blog_edit.html 1. JMeter介绍 环境要求&#xff1a;要求java&#xff0c;jdk版本大于8&#xff1b; Apache JMeter 是 Apache 组织基于 Java 开发的压⼒测试⼯具&#xff0c;⽤于对软件做性能测试&#xff1b…

带新手用一套坦克大战搞定Java核心编程

有不少在校大学生朋友私信笔者&#xff0c;觉得现在的Java教程学的比较枯燥&#xff0c;有没有能学到基础知识同时还有做项目感觉的教程。因为笔者最早接触Java时学的是马士兵老师、韩顺平老师这样的大佬当时出的教程&#xff0c;尤其印象深刻的是二位大佬的坦克大战项目&#…

基于DSP+ARM+FPGA的电能质量分析仪的软件设计

软件设计是电能质量设备的核心内容&#xff0c;上述章节详细介绍了电能质量参数的 算法&#xff0c;并且通过仿真实验进行了验证&#xff0c;本章将结合现代电能质量监测设备需求实 现算法在实际电网中应用。根据设计的电能质量分析仪的需求分析&#xff0c;进行总体的 软件…

Java筑基之路:运算符深入(下)

&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d; &#x1f947;博主昵称&#xff1a;小菜元 &#x1f35f;博客主页…

计算机网络:数据链路层 —— 共享式以太网

文章目录 共享式以太网CSMA/CD 协议CSMA/CD 协议 的基本原理 共享式以太网的争用期共享式以太网的最小帧长共享式以太网的最大帧长共享式以太网的退避算法截断二进制指数退避算法 共享二进制以太网的信道利用率使用集线器的共享式以太网10BASE-T 共享式以太网 共享式以太网是当…

51单片机数码管循环显示0~f

原理图&#xff1a; #include <reg52.h>sbit dulaP2^6;//段选信号 sbit welaP2^7;//位选信号unsigned char num;//数码管显示的数字0~funsigned char code table[]{ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};//定义数码管显…

yakit使用教程(四,信息收集)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言&#xff1a;yakit下载安装教程。 一&#xff0c;基础爬虫。 在新建项目或新建临时项目后&#xff0c;点击安全工具&#xff0c;点击基础爬虫。 此工具并不是为了爬取网站上的一…

navicat下载教程(包会的)

目录 一、下载navicat安装包 步骤1---试用版本 步骤2---下载windws系统的navicat​编辑 步骤3---查看安装包 二、安装navicat 三、唤醒navicat 四、成功唤醒navicat 官网地址&#xff1a;Navicat | 下载 Navicat Premium 14 天免费 Windows、macOS 和 Linux 的试用版 …

[Linux] 创建可以免密登录的SFTP用户

本文主要包含: 创建新用户创建密钥对用于免密登录新用户将新建用户改造为SFTP用户为SFTP上传数据设置限速 1. 创建新用户 sudo useradd sftp_user sudo passwd sftp_user # 输入密码2. 创建密钥对 参考这篇文章 [Linux] 生成 PEM 密钥对实现服务器的免密登录 3. 将新建用户…

牛客习题—线性DP 【mari和shiny】C++

你好&#xff0c;欢迎阅读我的文章~ 个人主页&#xff1a;Mike 所属专栏&#xff1a;动态规划 mari和shiny mari和shiny ​ 分析: 使用动态规划的思路来解决。 思路&#xff1a; 分别统计s&#xff0c;sh&#xff0c;shy的数量即可。使用ss来统计字符s的数量&#xff0c;使…