我需要创建一个只能执行一次的函数,在第一次之后的每次都不会执行。我从 C++ 和 Java 知道可以完成这项工作的静态变量,但我想知道是否有更优雅的方法来做到这一点?
JavaScript 中只能调用一次的函数
IT技术
javascript
function
design-patterns
2021-01-21 03:10:32
6个回答
如果“不会被执行”的意思是“多次调用时什么都不做”,则可以创建一个闭包:
var something = (function() {
var executed = false;
return function() {
if (!executed) {
executed = true;
// do something
}
};
})();
something(); // "do something" happens
something(); // nothing happens
回答@Vladloffe 的评论(现已删除):使用全局变量,其他代码可以重置“已执行”标志的值(无论您为它选择什么名称)。使用闭包,其他代码无法做到这一点,无论是意外还是故意。
正如这里的其他答案所指出的那样,一些库(例如Underscore和Ramda)有一个小实用函数(通常名为once()
[*]),它接受一个函数作为参数并返回另一个函数,该函数只调用一次提供的函数,无论如何多次调用返回的函数。返回的函数还缓存由提供的函数首先返回的值,并在后续调用中返回该值。
但是,如果您没有使用这样的第三方库,但仍然想要一个实用程序函数(而不是我上面提供的 nonce 解决方案),那么它很容易实现。我见过的最好的版本是David Walsh 发布的这个版本:
function once(fn, context) {
var result;
return function() {
if (fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
我倾向于fn = null;
改为fn = context = null;
. 没有理由让闭包保持对context
曾经fn
被调用过的引用。
用法:
function something() { /* do something */ }
var one_something = once(something);
one_something(); // "do something" happens
one_something(); // nothing happens
[*] 不过,请注意,其他库,例如jQuery 的 Drupal 扩展,可能有一个名为的函数once()
,它的功能完全不同。
将其替换为可重复使用的 NOOP (无操作)功能。
// this function does nothing
function noop() {};
function foo() {
foo = noop; // swap the functions
// do your thing
}
function bar() {
bar = noop; // swap the functions
// do your thing
}
调用后指向一个空函数:
function myFunc(){
myFunc = function(){}; // kill it as soon as it was called
console.log('call once and never again!'); // your stuff here
};
<button onClick=myFunc()>Call myFunc()</button>
或者,像这样:
var myFunc = function func(){
if( myFunc.fired ) return;
myFunc.fired = true;
console.log('called once and never again!'); // your stuff here
};
// even if referenced & "renamed"
((refToMyfunc)=>{
setInterval(refToMyfunc, 1000);
})(myFunc)
UnderscoreJs 有一个函数可以做到这一点,underscorejs.org/#once
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
说到静态变量,这有点像闭包变体:
var once = function() {
if(once.done) return;
console.log('Doing this once!');
once.done = true;
};
once(); once();
如果你愿意,你可以重置一个函数:
once.done = false;