我有这样的功能:
function run(arg) {
if (!window.alreadyRun) init();
window.alreadyRun = true;
/* more code */
}
你明白了,我想弄清楚这是否是第一次调用函数。
有更好的方法吗?不使用全局变量?像这样:
function run(arg) {
var ranAlready;
if (!ranAlready) init();
ranAlready = true;
/* more code */
}
答案 0 :(得分:5)
这将返回一个函数,其中包含一个名为runCount
的变量,该变量将保存它被调用的次数。
var yourFunction = function() {
var runCount = 0;
return function() {
console.log(runCount);
runCount++;
}
}
var a = yourFunction();
a(); // runCount: 0
a(); // runCount: 1
a(); // runCount: 2
a(); // runCount: 3
如果您只想运行init类型函数,可以将代码放在上面,返回内部函数。它将在返回内部函数之前调用一次,并且其作用域将保留其外部函数。
答案 1 :(得分:2)
关闭的力量。
var f = (function(run) {
return function() {
if (!run) init(),run=true;
// do code
};
}(false));
如果您希望在下一次函数调用中再次调用if (!run) init() && run = true
,您甚至可以使用init
并让false
返回run
。
我们有一个自执行函数,它创建一个本地false
变量,并将其作为参数传递给false
。然后,我们有一行检查它是否为init(), run=true
,如果是init
,它运行const
函数并在单个表达式中将其赋值为true。
基本上你在使用全局范围来使变量为函数静态,你可以使用闭包作为本地函数范围和范围之间的范围级别。全球范围。
如果你需要一个对函数静态的变量&只读,您可以使用鲜为人知的{{1}}关键字。
答案 2 :(得分:1)
我认为闭包对此完全过分,只会使代码复杂化。
您所描述的内容在面向对象语言中被称为静态变量,通过将属性直接附加到函数,可以很容易地在JS中模仿它。这是可能的,因为函数是JS中的第一类对象:
function run(arg) {
if (!run.ranAlready) { // run.ranAlready is undefined at first, so falsy
run.ranAlready = true;
init();
}
/* more code */
}
这比嵌套函数简单得多,您可以以完全相同的方式继续使用run()
。
另一个优点是,对于单元测试,您仍然可以从函数外部访问ranAlready
属性,以检查您的代码是否正常工作:
assert(run.runAlready == false);
run();
assert(run.runAlready === true);
当然,这不能用于匿名函数,例如在事件处理程序中,但是给匿名函数命名而不是使用嵌套函数和额外函数不是更清晰函数调用?
答案 3 :(得分:0)
这是另一种方法。您可以让函数自行修改。在下面的情况中,myfunction
将更改为新的。这个可能可能不是你正在寻找的东西,但我认为至少发布这个是有用的,所以你可以看到其他方法来做事情(还有:自修改代码有时候很酷) )。
var myfunction = function() {
alert("This is the first time I'm executed");
myfunction = function() {
alert('Subsequent times');
}
}
myfunction(); // displays the alert 'This is the first time...'
myfunction(); // displays the alert 'Subsequent times'
myfunction();