也许是一个奇怪的问题,但在这里:我有一个我定期调用的函数,在该函数中我需要知道我所处的迭代次数,或函数被调用了多少次。问题的简化版本:
jQuery( document ).ready( function(){
setInterval( "myFunction()", 3000 );
});
function myFunction()
{
alert( "I have been called X times" );
}
那么,我如何在上面的代码中找出X?
答案 0 :(得分:25)
简易版:在nyarlathotep's answer中创建一个全局变量。问题 - 如果其他一些代码也定义了一个具有相同名称的全局变量,那么你们都遇到了麻烦。
简易扩展版 - 为变量赋予一个没人会使用的疯狂名称:calledTimesED7E69A7B141457CA8908A612E3D7A3A
聪明的版本:将该变量附加到现有的全局变量。记住 - 一切都是 Javascript中的对象!
$(function(){ setInterval(myFunction, 3000); });
function myFunction()
{
myFunction.calledTimes++;
alert( "I have been called " + myFunction.calledTimes + " times" );
}
myFunction.calledTimes = 0;
传统版本:使用范围来隐藏该变量。
$(function()
{
calledTimes = 0;
setInterval(function()
{
calledTimes++;
alert( "I have been called " + calledTimes + " times" );
}, 3000);
});
这隐藏了“myFunction”,所以让我们再次尝试使用一种棘手的范围:
var myFunction = null;
(function()
{
calledTimes = 0;
myFunction = function()
{
calledTimes++;
alert( "I have been called " + calledTimes + " times" );
}
})();
$(function () { setInterval(myFunction, 3000); });
...还有很多其他方法可以隐藏该变量并使用范围。只需选择你喜欢的。
答案 1 :(得分:17)
您可以简单地使用一个全局变量,每次调用该函数时都会增加该变量:
var myFuncCalls = 0;
function myFunction()
{
myFuncCalls++;
alert( "I have been called " + myFuncCalls + " times" );
}
一旦你的代码变得更复杂(或者你使用了很多其他库),你应该考虑使用范围,如其他答案所示(one by Vilx中最好的解释) )。
答案 2 :(得分:9)
这是另一个不使用外部变量的有趣解决方案。关于这一点最好的部分是你可以保持任何预先存在的功能不受影响,并像平常一样调用它们。这意味着如果您尝试“点击”现有库中的某个功能,这将非常适合您。它增加了一个不显眼的计数器,允许您继续正常调用现有函数;即使有争论!
// no js library required
// pre-existing function
var a = function(){
console.log("pre-existing function function");
console.log("arguments:", arguments);
};
// add counter func
var addFnCounter = function(target){
var swap = target;
var count = 0;
return function(){
swap.apply(null, arguments);
count++;
console.log("func has been called " + count + " times");
console.log("\n");
};
};
// usage
a = addFnCounter(a);
// call a() as you would normally
a();
a(1,2,3);
a('hello', 'world');
// using your setInterval example
setInterval(a, 3000);
pre-existing function function
arguments: []
func has been called 1 times
pre-existing function function
arguments: [1, 2, 3]
func has been called 2 times
pre-existing function function
arguments: ["hello", "world"]
func has been called 3 times
setInterval
输出pre-existing function function
arguments: []
func has been called 4 times
pre-existing function function
arguments: []
func has been called 5 times
pre-existing function function
arguments: []
func has been called 6 times
答案 3 :(得分:7)
你必须使用一个闭包。 通常你会使用一个静态变量。在Javascript中它看起来像:
jQuery( document ).ready( function(){
setInterval( myFunction, 3000 );
});
var myFunction = (function(){
var count = 0;
return function(){
count++
alert( "I have been called " + count + " times");
}
})();
答案 4 :(得分:2)
与其他答案中的闭包或装饰器相比,静态变量更清晰,也不会污染您的外部范围。
var foo = function(){
alert( ++foo.count || (foo.count = 1) );
}
// test
function callTwice(f){ f(); f(); }
callTwice(foo) // will alert 1 then 2
或
callTwice( function bar(){
alert( ++bar.count || (bar.count = 1) );
}); // will alert 1 then 2
第二个是名为匿名函数的 。请注意这种语法:
var foo = function bar(){ /* foo === bar in here */ }
答案 5 :(得分:0)
创建一个全局变量并初始化为零。然后在myfunction()调用时递增1。显示该变量而不是 X 。
答案 6 :(得分:0)
您可以使用 Proxy 为您的函数使用 apply()
trap:
const addCounter = fn => {
let count = 0; // keep count
//define handler
const handler = {
apply() {
//do something with this counter
console.log(`I have been called ${++count} times `);
return Reflect.apply(...arguments); //call the function normally
}
}
//wrap the function into a proxy that uses the handler and return it
return new Proxy(fn, handler);
}
setInterval( addCounter(myFunction), 1000 );
function myFunction() { //sample operation - move an image
const img = document.querySelector("img");
let offset = img.offsetLeft + 10;
if (offset > 100) //return to start
offset = 0;
img.style.left = `${offset}px`;
}
img {
position: absolute;
}
.as-console-wrapper {
max-height: 45px !important;
}
<img src="https://picsum.photos/150" />