vscode工具函数once使用示例深入剖析

目录
  • 背景
  • VSCode中的实现
  • lodash的实现
  • once的应用
  • once的注意事项
    • this指针问题
  • 小结

背景

once 函数的起源可以追溯到函数式编程。在函数式编程中,函数被视为不可变的,这意味着它们不应修改任何状态或引用任何状态。因此,在函数式编程中,通常需要一些技巧来处理一些常见问题,例如避免在多次调用相同函数时进行冗余计算。

once 函数是解决此问题的一种方法。它可以将函数转换为只能调用一次的函数,并使用一些技巧来避免冗余计算。使用 once 函数可以减少计算时间和资源的消耗,并提高应用程序的性能。

once 函数在现代 JavaScript 库和框架中非常常见,例如 lodash。它们提供了许多内置的 once 函数来处理各种场景和问题。在实际开发中,我们可以使用这些函数来提高代码的可维护性和可读性,避免冗余计算和网络请求,并提高应用程序的性能。

VSCode中的实现

export function once<T extends Function>(this: unknown, fn: T): T {
	const _this = this;
	let didCall = false;
	let result: unknown;
	return function () {
		if (didCall) {
			return result;
		}
		didCall = true;
		result = fn.apply(_this, arguments);
		return result;
	} as unknown as T;
}

这个实现比较简单,但还是详细分析解释一下代码

  • 函数签名:once<T extends Function>(this: unknown, fn: T): T。该函数使用了泛型参数**T,表示被封装的原始函数的类型。它还定义了一个this参数,表示封装函数中的this关键字的类型为unknown,以及一个fn**参数,表示被封装的原始函数。
  • 缓存结果:在函数内部,定义了三个变量。**_this变量引用了函数中的this关键字,并将其保存在变量中。didCall变量用于跟踪函数是否已经被调用过。result**变量用于保存函数的结果。
  • 返回新函数:函数内部返回了一个匿名函数,它接受任意数量的参数,并将其传递给原始函数。在函数内部,首先检查函数是否已经被调用过。如果是,则直接返回之前保存的结果。否则,将**didCall**标记为已调用,并调用原始函数并保存结果。最后,返回结果。
  • 类型断言:函数的返回值是一个匿名函数,但是它的类型需要与原始函数相同。因此,使用了一个类型断言将匿名函数的类型强制转换为泛型参数**T**。

lodash的实现

lodash 到目前的版本已经是高度封装了,它的源码可以在**github.com/lodash/loda…**看到:

function once(func) {
  return before(2, func)
}

它本身是调用了 before 函数, before 是一个经过高度抽象的函数,它在被调用次数达到指定次数之前,会继续执行传入的函数,而在达到指定次数时,会返回最后一次执行传入函数的结果:

function before(n, func) {
  let result
  if (typeof func !== 'function') {
    throw new TypeError('Expected a function')
  }
  return function(...args) {
    if (--n > 0) {
      result = func.apply(this, args)
    }
    if (n <= 1) {
      func = undefined
    }
    return result
  }
}

对于 lodash 这样的工具库而言,它的抽象层次要比 vscode 更高,但实现的原理是相同的,核心都是利用闭包,通过内部变量的状态来判断函数是否已经被调用过,从而保证原始函数只被执行一次。

once的应用

**once**函数是一个常见的JavaScript函数,它用于确保一个函数只能被调用一次。这个函数在以下几个场景下非常有用:

  • 缓存函数的结果:当一个函数需要执行复杂的计算时,我们可以使用**once**函数来确保它只会被调用一次,并将结果缓存下来。在之后的调用中,函数会直接返回缓存的结果,而不会再次执行计算。这可以节省计算时间和资源,并提高应用程序的性能。
  • 避免重复网络请求:当我们需要向服务器发送请求时,可以使用**once**函数来确保只发送一次请求,并在之后的调用中直接返回结果。这可以避免发送重复的网络请求,并提高应用程序的响应速度。
  • 确保只运行一次的初始化代码:有时候我们需要在应用程序启动时执行一些初始化代码,例如创建全局变量或注册事件处理程序。在这种情况下,可以使用**once**函数来确保这些代码只会被执行一次,避免不必要的重复操作。

在VSCode中, once 用的非常频繁,通过查看 reference 我们可以看到非常多的使用:

once的注意事项

this指针问题

once 函数内部,定义了一个名为 _this 的变量,它保存了函数的 this 关键字。这是因为,在使用 applycall 方法调用函数时,需要确保函数中的 this 关键字被正确地绑定。如果没有保存 _this 变量,而是直接使用 this 关键字,可能会导致 this 关键字在多次调用中被意外地修改,从而导致错误或异常。

在使用 once 函数时,如果原始函数需要使用 this 关键字,需要确保 this 关键字被正确地绑定。看看以下代码:

class Counter {
  private count = 0;
  constructor(private readonly name: string) {}
  increment() {
    console.log(`${this.name}: Count = ${++this.count}`);
  }
}
const counter1 = new Counter('Counter 1');
const counter2 = new Counter('Counter 2');
const incrementOnce = once(counter1.increment);
incrementOnce.call(counter1); // 输出 "Counter 1: Count = 1"
incrementOnce.call(counter2); // 输出 "Counter 1: Count = 2",而不是 "Counter 2: Count = 1"
incrementOnce.call(counter1); // 输出 "Counter 1: Count = 2"

在上述代码中,如果我们在多次调用 incrementOnce 函数时,使用了不同的 this 关键字,可能会导致输出结果不正确。例如,上述代码中的第二次调用 incrementOnce 函数时,使用了 counter2 作为 this 关键字,而实际上 incrementOnce 函数中保存的 this 关键字是 counter1,因此输出结果为 "Counter 1: Count = 2",而不是 "Counter 2: Count = 1"。

因此,在使用 once 函数时,需要确保原始函数能够正确地处理 this 关键字,并且在调用 once 函数时,应该指定正确的 this 关键字,以避免意外的错误或异常。

小结

本文对 once 函数进行了详细的剖析,包括其背景、实现原理和应用场景。在实际开发中,once 函数可以用于缓存函数的结果、避免重复网络请求以及确保只运行一次的初始化代码。在使用 once 函数时,需要注意原始函数的 this 关键字的绑定,以避免意外的错误或异常。

在我们的日常开发中,见过太多的代码为了保证只执行一次,在本地定一个类似 flag 的变量来控制,这种写法非常不优雅,在这种场景下,使用 once 函数是一个更好的选择。

以上就是vscode工具函数once使用示例深入剖析的详细内容,更多关于vscode工具函数once的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue使用once修饰符,使事件只能触发一次问题

    目录 once修饰符,使事件只能触发一次 vue事件修饰符(once:prev:stop) 注释说的很详细 once修饰符,使事件只能触发一次 多个修饰符可以同步使用 <!--定义vue的操作对象--> <div id="app">     <!-- 使用self修饰符 点击标签自身时才会执行事件 -->     <!-- 使用once修饰符 使事件只能触发一次  -->     <!-- 多个修饰符可以同时使用   -->

  • vscode输入npm install报错:node-sass@8.0.0 install:'node scripts/install.js'解决

    目录 报错信息描述 第一种:看一下这里是否有中文目录,有的话有可能会报错. 第二种.管理员身份运行vscode 第三种: node-sass版本问题 解决版本问题方案: 总结 报错信息描述 当我们在vscode中输入npm install 命令时,报如下的错误信息: 报错的原因及解决方案(自身入的坑): 第一种:看一下这里是否有中文目录,有的话有可能会报错. 我是把快速开发的项目拉取到桌面上然后以Vscode运行该项目的,默认给我放入的是C盘(我C盘带中文目录,因此报错了),如果想要解决这个中文

  • vue指令中的v-once用法

    目录 v-once在日常开发中用的很多 常见用法如下 v-once是什么 v-once在日常开发中用的很多 只渲染元素和组件一次,随后的渲染,使用了此指令的元素/组件及其所有的子节点,都会当作静态内容并跳过,这可以用于优化更新性能. 常见用法如下 当修改input框的值时,使用了v-once指令的p元素不会随之改变,而第二个p元素时可以随之改变的 <div id="app">         <p v-once>{{msg}}</p>  //msg不

  • VSCode多行注释插件KoroFileHeader使用示例

    目录 1.简介 主要功能 2.安装 3.使用 默认快捷键 文件头部注释快捷键 函数注释快捷键 图案注释快捷键 自定义快捷键 4.插件自定义配置 1.简介 VSCode插件: 用于一键生成文件头部注释并自动更新最后编辑人和编辑时间.函数注释自动生成和参数提取. 插件可以帮助用户养成良好的编码习惯,规范整个团队风格. 主要功能 自动生成文件头部注释,自动更新最后编辑人.最后编辑时间等. 一键生成函数注释,支持函数参数自动提取并列到注释中. 支持添加佛祖保佑永无bug.神兽护体.甩葱少女等好玩有趣的图

  • VSCode中 Eslint 和 Prettier 冲突问题最新解决方法

    目录 前言 为什么会冲突 Eslint Prettier 冲突 解决 前言 本次环境皆为 @vue/cli默认安装带有的 eslint@7.32.0,VSCode 插件版本: Eslint v2.4.0 Prettier v9.10.4 为什么会冲突 首先我们需要知道为什么使用Eslint 和 Prettier,下面先介绍两者的单独用法 Eslint Javascript Vue Typescript 等文件的代码规范检测工具,当代码写法不符合时,会在终端进行报错提醒,阻止你的serve服务.为

  • vscode不支持nvue语法高亮的解决办法(图文详解)

    目录 项目场景: 问题描述 原因分析: 解决方案: 配置如图 解决效果 项目场景: 项目场景:用vscode开发uniapp会遇到用.nvue开发的时候.但是vscode并没有提供.nvue的语法高亮,这篇文章给刚用vscode写.nvue的读者 问题描述 例如:vscode中使用*.nvue识别不出文件类型,没有语法高亮如图: 原因分析: 我这里用的插件是vue3语法支持的Volar,网上铺天盖地的vetur解决方案,其实只要vscode配置一下就行 解决方案: 配置如图 解决效果 到此这篇关

  • vscode工具函数once使用示例深入剖析

    目录 背景 VSCode中的实现 lodash的实现 once的应用 once的注意事项 this指针问题 小结 背景 once 函数的起源可以追溯到函数式编程.在函数式编程中,函数被视为不可变的,这意味着它们不应修改任何状态或引用任何状态.因此,在函数式编程中,通常需要一些技巧来处理一些常见问题,例如避免在多次调用相同函数时进行冗余计算. once 函数是解决此问题的一种方法.它可以将函数转换为只能调用一次的函数,并使用一些技巧来避免冗余计算.使用 once 函数可以减少计算时间和资源的消耗,

  • JavaScript中cookie工具函数封装的示例代码

    一. 语法 1.1 获取当前页面的所有cookie: var allCookies = document.cookie; allCookies 是一个字符串,其中包含了以分号分隔的cookie列表字符串 (即 key=value 键值对). 1.2 写一个新cookie: document.cookie = updatedCookie; updatedCookie是一个键值对形式的字符串.只能用这个方法一次设置或更新一个cookie,而且写入并不是覆盖,而是添加.例如: document.coo

  • js实现的光标位置工具函数示例

    本文实例讲述了js实现的光标位置工具函数.分享给大家供大家参考,具体如下: 这里介绍的一款textarea中光标位置工具函数的例子. html代码: <p>文本框:</p> <textarea name="" id="textarea" cols="30" rows="10"> sASASADASDasfaDFDsfsDFAfdFADf </textarea> <butto

  • 实例解析jQuery工具函数

    一.$.browser对象属性 属性列表 说明 webkit webkit相关浏览器则返回true,否则返回false,如google,傲游.    mozilla mozilla相关浏览器则返回true,否则返回false,如火狐 safari    safari相关浏览器则返回true,否则返回false,如safari opera   opera相关浏览器则返回true,否则返回false,如opera msie msie相关浏览器则返回true,否则返回false,如IE,360,搜狗

  • 从零开始学习jQuery (九) jQuery工具函数

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 我们经常要使用脚本处理各种业务逻辑, 最常见的就是数组和对象的操作. jQuery工具函数为我们操作对象和数组提供了便利条件. 二.前言 大部分人仅仅使用jQuery的选择器选择对象, 或者实现页面动画效果. 在处理业务逻辑时常常自己编写很多算法. 本文提醒各位jQuery也能提高我们操作对象和数组的效率. 并且可以将一些常用算法扩充到jQuer

  • Vue组件大全包括(UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例)

    Vue是一款比较流行的JS库,本文为大家介绍一些Vue组件,包括UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例等开源项目 一.Vue常用UI组件 element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组件库 iview ★5801 - 基于 Vuejs 的开源 UI 组件库 mint-ui ★5517 - Vue 2的移动UI元素 vue-material ★2790 - 通过Vue Material和Vue 2

  • JavaScript常用工具函数库汇总

    对象或数组的深拷贝 /** * 对象或数组的深拷贝 * @param {*} cloneObj 被克隆的对象 * @param {*} targetObj 克隆的目标对象 * @param {*} isOverride 若属性重复,是否覆盖被克隆对象的属性 */ function deepClone(cloneObj, targetObj, isOverride = true) { const _toString = Object.prototype.toString if (_toString

  • Java常用工具类汇总 附示例代码

    一.FileUtils private static void fileUtilsTest() { try { //读取文件内容 String readFileToString = FileUtils.readFileToString(new File("D:\\guor\\data\\test20211022000000.txt")); System.out.println(readFileToString); //删除文件夹 FileUtils.deleteDirectory(ne

  • uni-app使用微信小程序云函数的步骤示例

    创建云函数目录 首先,我们需要在uni-app项目文件夹下,创建一个云函数目录,路径随意,我这里是functions.然后先随便在里面放一些文件,这里以new_file.css为例.(放文件的原因是:确保编译成小程序后cloudfunctions文件夹存在.如果该文件夹下没有文件,默认是不会在微信小程序开发平台中显示该文件夹的.) 修改manifest.json 在uni-app根目录下,修改manifest.json中的微信小程序项,结构如下 "mp-weixin" : { /* 小

  • Vue项目中常用的工具函数总结

    目录 前言 一.自定义聚焦指令 1.方式一 2.方式二 3.方式三 二.输入框防抖 1.需求 2.思路 3.代码实现 三.关键字高亮 1.需求 2.思路 3.代码演示 四.格式化Excel表格中存储的时间 1.需求 2.代码演示 总结 前言 本文记录了一些Vue项目中常用的工具函数,为了工具函数的统一管理,统一将这些函数放到src目录下的utils文件夹里 一.自定义聚焦指令 1.方式一 mouted周期,ref+querySelector获取到input标签,调用focus() 2.方式二 自

随机推荐