2010-07-26 67 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