2013-10-25 58 views
1

我有一個函數 - 我們將其定義爲function getdata(after){},它將after參數作爲一個函數。很自然。此功能是從能在其範圍定義了一些變量的一些其他功能運行:javascript函數作爲參數和作用域變量

$('.button').click(function(){ 
    var rel = $(this).attr('rel'); 
    var mooo = $(this).parent().offset().left; 
    getdata(function(){alert(rel);console.log(moo)}); 
}); 

我如何通過這些變量正確的方法,所以這真的是同一件事,因爲它是點擊該按鈕時?它不能是全局變量,因爲用戶可以點擊垃圾郵件按鈕,並且它應該保持變量在點擊過程中的準確位置,即使當函數在10分鐘後以隨機順序被調用時也是如此,因爲正如名稱所說 - 正在稱爲AFTER ajax請求。

這只是一個例子 - 這個想法是這個after函數也是可變的,從完全不同的地方調用。


好,我知道-1,因爲目前還不清楚我要求的,所以我試圖解釋這一問題。我真的不明白什麼時候變量作爲變量傳遞,何時作爲變量的指針傳遞,變量的指針可能會在它傳遞給它的函數使用之前發生變化。

當我在一個函數中定義變量並將其傳遞給另一個函數時,它是一個指針還是一個獨立變量?當我再次調用原點函數時,這些變量將會改變 - 它會影響之前「調度」的函數嗎?或者變量之前的單詞var意味着 - 將其定義爲完全新鮮的變量,並且每次調用var的函數時,它都會將該變量作爲全新的變量分配給內存,這是發生任何事情的最後一個變量?

我通常是一個PHP,C和Delphi編程人員,對於我來說,瞭解這些變量作用域的工作原理有點困難,特別是當所有事情都是異步和回調時。

+0

除非發送到該函數的參數是一個對象,它將傳遞它的值而不是它的引用。當你發送一個字符串('$(this).attr('rel')'屬性)和一個整數('$(this).offset()。left')時,你不需要擔心getdata可能會延遲調用回調。打印回調中的變量將包含按鈕被點擊時的值。 –

+0

如何確定它是作爲字符串還是對象傳遞的? '$(this).offset()'是一個對象,'$(this).offset()。left'是獨立的字符串?如果我想傳遞'$(this)'sender對象,以便能夠在函數完成後更改對象呢? –

+0

@FlashThunder查看我更新的答案。我不建議你使用它,但它可以讓你洞察變量範圍和JS的動態特性。 –

回答

2

簡單地說,在javascript中,簡單類型(字符串,數字,布爾值)通過值傳遞,而對象通過引用傳遞。 see this question for a real detailed answer

如果你不知道你要多少個參數來處理(或它們的類型),那麼你可以使用arguments array

var getdata = function(){ 
    //your function logic 

    //arguments is an array with all the args 
    //the last one is the "after" function 
    var after = arguments[arguments.length-1]; 
    return after(arguments); 
}; 

$('.button').click(function(){ 
    var rel = $(this).attr('rel'); 
    var mooo = $(this).parent().offset().left; 
    getdata(rel, moo, /*add all the arguments you want here...*/, function(args){ 
     alert(args[0]); 
     console.log(args[1]) 
    }); 
}); 
+0

但是這些變量在類型和數量上可能完全不同。 –

+1

@FlashThunder你不能從JS中的範圍中獲取所有變量。您必須指定哪些變量可用於不屬於詞彙範圍的函數,也就是說,在外部函數的源代碼文獻中。查看http://stackoverflow.com/questions/1047454/what-is-lexical-scope –

+0

@FlashThunder你可以做的最好的事情就是傳遞一個單獨的對象,你可以添加任意多的屬性,以及任何你想要的類型 –

1

我不能確定你在問什麼,但這是rvignacio的答案的變化,從而爲任意數量的參數getdataafter

var getdata = function(after){ 
    //your function logic 
    return after.apply(null, [].slice.call(arguments, 1)); 
}; 

$('.button').click(function(){ 
    var rel = $(this).attr('rel'); 
    var mooo = $(this).parent().offset().left; 
    getdata(function(rel_param, moo_param){ 
     console.log(rel_param); 
     console.log(moo_param) 
    }, rel, moo); 
}); 
+0

OP想要傳入的函數可以使用相同的變量範圍,但在JS中不可能,只有詞法變量範圍。 –

1

如你所描述你不能這樣做完全是。你要做的是將alll關聯的關閉傳遞給回調函數。在JavaScript中,使用變量的詞彙範圍。這意味着

function outer (callback) { 
    var a = 1, b = 2, c = 3; 
    var inner = function() { 
    // This works because inner is defined inside of outer 
    // and has access to a,b,c 
    console.log(a,b,c); 
    }  
    inner(); 
    callback(); 
} 

outer(function() { 
    // This won't work because it doesn't know where to get a,b,c from 
    // Some languages may(could/allow?) this, JS doesn't 
    console.log(a,b,c); 
}); 

因此,要解決您的問題,您必須通過傳遞它們作爲參數來指定要提供給回調的變量。 rvignaciobfavaretto已經向您展示如何做到這一點

的eval()爲贏(的損失,真的)

OK,還有一個辦法,但它需要eval,所以你should't使用。無論如何,這是有趣的。eval()確實在相同的範圍內執行,所以通過在詞法範圍內添加一個eval並調用它的回調函數,您可以實現您想要的效果。再次,我不是建議你這樣做。它打破封裝並且回調不應該知道其調用者的私有者。但只是爲了它的樂趣... http://jsfiddle.net/zbwd7/1/

/** 
* The callback will accept a single argument, it's a function that takes the name 
* of the variable you want to use and returns its value. DON'T EVER DO THIS IN REAL CODE 
* @callback {function(string): *} getVar The function that gives you access to the 
* caller's scope 
* @callback.varName {string} The name of the variable to retrieve 
* @callback.return {*} The value of the variable 
*/ 
function outer (callback) { 
    var a = 1, b = 2, c = 3; 

    function getVar(varName) { 
     return eval(varName); 
    }  
    callback(getVar); 
} 


outer(function(getVar) { 
    // outputs one, two, three 
    console.log(getVar("a"), getVar("b"), getVar("c")); 
});