首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JS实现只能调用一次的函数

JS实现只能调用一次的函数

作者头像
kifuan
发布于 2022-10-24 08:56:33
发布于 2022-10-24 08:56:33
2.7K00
代码可运行
举报
文章被收录于专栏:随便写写-kifuan随便写写-kifuan
运行总次数:0
代码可运行

源码

前往Github获取本文源码。

目标

我们的想法是一个函数只有第一次调用的时候有效,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function foo() {
    console.log('Hello world')
}

foo()
foo()
foo()

毋庸置疑,它会打印出三个Hello world。这篇文章就是来看看通过哪个方式能让他只打印一个。

第一想法

如果它是在一个对象里面,这个事就好办了,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const obj = {
    hello() {
        console.log('Hello from obj')
        this.hello = () => {}
    }
}

obj.hello()
obj.hello()

无论后面调用多少次,因为我们已经让this.hello变成了一个空函数,所以都不会再次打印了。但是,我们的目标是没有obj.这个前缀。或许你可能会想到用bind解决这个问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const obj = {
    hello() {
        console.log('Hello from obj')
        this.hello = () => {}
    }
}

const hello = obj.hello.bind(obj)
hello()
hello()

但是,你可以自己试一下,这是没用的。因为在这个函数里面设置的obj.hello已经和我们赋值出去的const hello没有关系了。

最终方案

还是要请出我们的老朋友Proxy来解决这个问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function once(f) {
    let called = false

    function apply(target, thisArg, args) {
        if (called) {
            return
        }
        called = true
        return Reflect.apply(target, thisArg, args)
    }

    return new Proxy(f, { apply })
}

通过一个布尔变量called来保存这个函数是否已经被调用,那么之后我们就可以这样写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const foo = once(() => {
    console.log('Hello from foo')
})

foo()
foo()
foo()

无论调用多少遍只会执行第一次,达成目的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
js 实现 bind 的这五层,你在第几层?
这个时候,我马老师就坐不住了,我不服气,我就去复习了一下 bind,发现太久不写基础代码,还是会需要一点时间复习,这一次我得写一个有深度的 bind,深得马老师的真传,给他分成了五层速记法。
秋风的笔记
2021/05/31
6280
几种常见的手写源码实现
简单版深拷贝,列举三个例子 array object function,可以自行扩展。主要是引发大家的思考
前端迷
2020/02/02
1K0
Reflect
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect对象的设计目的有这样几个。
小小杰啊
2022/12/21
5200
代理与反射(二)
通过添加对应捕获器,就可以捕获get、set、has等操作,可以监控这个对象何时在何处被访问过,并且能在访问、修改前干想干的事,并通过反射重新实现原功能。
赤蓝紫
2023/03/16
1940
代理与反射(二)
面试官问:能否模拟实现JS的bind方法(高频考点)
先看一下bind是什么。从上面的React代码中,可以看出bind执行后是函数,并且每个函数都可以执行调用它。眼见为实,耳听为虚。读者可以在控制台一步步点开例子1中的obj:
若川
2021/01/13
5740
猿创征文| ES 6 学习笔记6- Proxy
Proxy ​用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种​“元编程”​(meta programming),即对编程语言进行编程。
破晓之翼
2022/12/02
3850
ES6之Reflect详解
Reflect是ES6中新增的一个内置对象,它提供了一组静态方法,用于操作对象。这些方法与Object上的方法具有相同的功能。在这些方法中会调用对应Object上的方法,并且返回对应结果。Reflect的出现主要是为了将一些Object对象上的方法转移到Reflect上,使得操作对象更加统一和易于理解。通过这种方式,实现了对Object上方法的封装和统一。
can4hou6joeng4
2023/11/17
8480
【JS逆向百例】携某 testab 参数补环境详解
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
K哥爬虫
2024/08/19
1.1K0
【JS逆向百例】携某 testab 参数补环境详解
JavaScript 高级程序设计(第 4 版)- 代理和反射
ES6 新增的代理和反射提供了拦截并向基本操作嵌入额外行为的能力。即可以给目标对象定义一个关联的代理对象,而该代理对象可以作为抽象的目标对象来使用。在对目标对象的各种操作影响目标对象之前,可以在代理对象中对这些操作加以控制。 # 代理基础 # 创建空代理 const target = { id: 'target' }; const handler = {}; const proxy = new Proxy(target, handler); // id 属性会访问同一个值 console.log(ta
Cellinlab
2023/05/17
2970
JS_手写实现
今天,我们继续「前端面试」的知识点。我们来谈谈关于「JS手写」的相关知识点和具体的算法。
前端柒八九
2022/12/19
1.4K0
JS_手写实现
学习基础Proxy
Proxy是es6为我们新增的对象,和它的名字一样,它起到一个代理作用,可以拦截对对象的操作,比如获取数据,设置属性等。
kifuan
2022/10/24
4480
一文理解 this、call、apply、bind
记得差不多在两年多之前写过一篇文章 两句话理解js中的this,当时总结的两句话原话是这样的:
木子星兮
2020/03/17
4280
ES6之Reflect
将Object对象一些明显属于语言内部的方法放到Reflect对象上,比如Object.defineProperty,未来新方法只部署在Reflect对象上。
wade
2020/04/23
3860
ES6之Reflect
你知道多少this,new,bind,call,apply?那我告诉你
那么什么是this,new,bind,call,apply呢?这些你都用过吗?掌握这些内容都是基础中的基础了。如果你不了解,那还不赶快去复习复习,上网查阅资料啥的!
达达前端
2019/11/14
4040
JS 中的 Reflect 和 Proxy
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。Reflect不是一个函数对象,因此它是不可构造的。Reflect的所有的方法都是静态的就和Math一样,目前它还没有静态属性。
羽月
2022/10/08
1K0
死磕 36 个 JS 手写题(搞懂后,提升真的大)
作为一个程序员,代码能力毋庸置疑是非常非常重要的,就像现在为什么大厂面试基本都问什么 API 怎么实现可见其重要性。我想说的是居然手写这么重要,那我们就必须掌握它,所以文章标题用了死磕,一点也不过分,也希望不被认为是标题党。
用户4456933
2021/06/01
1K0
重学ES6之代理Proxy和反射Reflect
Proxy代理,Reflect反射。 调用new Proxy()可以创建代替其他目标(target)对象的代理,它虚拟化了目标,所以两者看起来功能一致。 代理可以拦截JavaScript引擎内部目标的底层对象操作,这些底层操作被拦截后会触发相应特定操作的陷阱函数。(钩子函数Hook) 反射API以Refelect对象的形式出现,对象中方法的默认特性与相同的底层操作一致,而代理可以覆写这些操作,每个代理陷阱对应一个命名和参数都相同的Refelect方法。 Tips 无论是Object.definP
19组清风
2021/11/15
6780
一文理解 this、call、apply、bind
记得差不多在两年多之前写过一篇文章 两句话理解js中的this[1],当时总结的两句话原话是这样的:
木子星兮
2020/07/17
4040
前端面试复习计划,保熟~
实现:getBoundClientRect 的实现方式,监听 scroll 事件(建议给监听事件添加节流),图片加载完会从 img 标签组成的 DOM 列表中删除,最后所有的图片加载完毕后需要解绑监听事件。
loveX001
2022/12/07
1.3K0
深入浅出 JavaScript Reflect API
作为开发人员,你需要创建能够处理动态代码的系统和应用程序。这些程序应该能够在运行时操作变量、属性和对象方法。为此,ES6 中引入了一个新的全局对象 Reflect,它能够处理简单的代码操作。
用户8921923
2022/10/24
5200
相关推荐
js 实现 bind 的这五层,你在第几层?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档