2010-07-26 79 views
11

我有一个JavaScript函数如何检测调用函数与JavaScript

如何检查

如果函数被调用(在<head></head>部分有此功能),则不会调用函数

如果功能当时不叫(在<head></head>部分还没有这个功能),然后调用函数

像require_once或include_once用php

帮我 感谢

+0

可能重复http://stackoverflow.com/questions/280389/how-do-you-find-out-the-caller-function -in-javascript) – Ralgha 2013-02-01 21:36:12

回答

24

两个选项:

静态变量下面是如何创建静态(如C语言)使用自调用函数存储在一个封闭的静态变量的变量。它运行后

var myFun = (function() { 
    var called = false; 
    return function() { 
    if (!called) { 
     console.log("I've been called"); 
     called = true; 
    } 
    } 
})() 

空函数替代将功能设置为空函数。

function callonce() { 
    console.log("I've been called"); 
    arguments.callee = function() {}; 
} 

摘要想法下面是返回一个只被调用一次函数,这样,我们就不必担心增加锅炉板代码的每个功能的函数。

function makeSingleCallFun(fun) { 
    var called = false; 
    return function() { 
    if (!called) { 
     called = true; 
     return fun.apply(this, arguments); 
    } 
    } 
} 

// Alternate implementation 
function makeSingleCallFun(fun) { 
    return function() { 
     return fun.apply(this, arguments); 
     arguments.callee = function() {}; 
    } 
} 

var myFun = makeSingleCallFun(function() { 
    console.log("I've been called"); 
}); 
myFun(); // logs I've been called 
myFun(); // Does nothing 
的[你如何找出在JavaScript中调用函数?(
+0

谁降低了这个? +1以余额 – 2011-01-29 11:21:05

+0

@SeanPatrickFloyd在开始时我认为'callee'是一个关于'called'函数名的错字,但它是一个变量并且匹配,所以我不知道为什么被低估。你在评论之前是否尝试了代码? – erm3nda 2016-01-06 05:33:04

+3

@ erm3nda不知道。这是4年前 – 2016-01-06 07:58:32

3
var called = false; 
function blah() { 
    called = true; 
} 

if (!called) { 
    blah(); 
} 
+1

对于那些全局变量纳粹[因为这是全局范围],你可以使用blah.called而不是var blah ...假设已经定义了blah。不过,这段代码对我来说已经足够了。 – Warty 2010-07-26 04:52:11

+0

这种模式的缺点是你必须在调用的任何地方将函数调用包装在条件语句中。 – 2010-07-26 11:59:12

+0

@ItzWartyTörökGábor指出,这对我来说还不够。有一个原因是全局变差,所以我避免他们像瘟疫一样,称我为全球纳粹!这里有很多其他的例子没有使用全局变量,也不需要用条件句柄来包装调用 – 2011-01-29 01:22:49

4

这很容易做到,因为JavaScript函数是可以拥有成员和属性的对象:

var callMeOnlyOnce=function(){ 

    if(this.alreadyCalled)return; 

    alert('calling for the first time'); 

    this.alreadyCalled=true; 
}; 

// alert box comes 
callMeOnlyOnce(); 


// no alert box 
callMeOnlyOnce(); 

编辑:

由于正确地指出由CMS,使用这并不容易。这是一个使用自定义命名空间而不是此的修订版本。

if(!window.mynamespace){ 
    window.mynamespace={}; 
} 

mynamespace.callMeOnlyOnce=function(){ 

    if(mynamespace.alreadyCalled)return; 

    alert('calling for the first time'); 
    mynamespace.alreadyCalled=true; 
}; 

// alert box comes 
mynamespace.callMeOnlyOnce(); 


// no alert box 
mynamespace.callMeOnlyOnce(); 
+1

'this'指的是全局对象,而不是函数本身,'allreadyCalled'将会最终成为Global对象的一个​​属性。这是因为该函数是从没有基础对象的引用调用的:'callMeOnlyOnce();'。 [更多信息'this'](http://stackoverflow.com/questions/3320677/this-operator-in-javascript/3320706#3320706) – CMS 2010-07-26 05:34:38

10

使用装饰模式。

// your function definition 
function yourFunction() {} 

// decorator 
function callItOnce(fn) { 
    var called = false; 
    return function() { 
     if (!called) { 
      called = true; 
      return fn(); 
     } 
     return; 
    } 
} 

yourFunction(); // it runs 
yourFunction(); // it runs  
yourFunction = callItOnce(yourFunction); 
yourFunction(); // it runs 
yourFunction(); // null 

此解决方案为实现您的目标提供了一种无副作用的方式。你不必修改你的原始功能。即使使用库函数,它也很好用。您可以为装饰功能指定一个新名称以保留原始功能。

var myLibraryFunction = callItOnce(libraryFunction); 
myLibraryFunction(); // it runs 
myLibraryFunction(); // null 
libraryFunction(); // it runs 
+0

哦,不,我跳过你的答案,并添加了一个几乎是相同。我会留下我的回答,因为我也展示了不同的方式。但是,这是如何装饰模式?我认为这更像是面向方面的编程。 – 2011-01-29 01:47:10

+0

@Juan你是对的,AOP经常使用装饰模式 – 2011-01-29 11:20:24

0
If (!your_func.called) { 
    your_func.called = true; 
    your_func(); 
} 
+0

在所有答案中,这是需要最多重复代码的答案。每次调用都需要设置标志并用条件包装。 – 2011-01-29 01:27:38