2016-05-10 23 views
1

我對JavaScript很有幫助。我試圖找出一種解決嵌套函數的方法。看看下面的兩個例子在不關閉的情況下使變量可用於異步調用

// example 1 
var x = 45; 
function apple(){ 
    var y = 60; 
    setTimeout(function(){ 
     console.log(y); 
     console.log(x); 
    }, 20); 
} 
apple(); 
console.log(x); 

嘛價值y保持並自setTimeout封閉形式與功能apple()其印在控制檯,它工作得很好。現在,就來看看下面的代碼

var x = 45; 
var run = function(){ 
     console.log(y); 
     console.log(x); 
}; 
function apple(){ 
    var y = 60; 
    setTimeout(run, 20); 
} 
apple(); 
console.log(x); 

我只是想單獨放置函數體,並通過函數處理器的說法,但我堅持了的是我怎麼做的功能apple()可用變量起作用run()因爲他們不再形成關閉。有沒有一種解決方法使它成爲可能?請幫助我。

請以通用的方式回答我,以便它也適用於nodejs API。我看到setTimeout接受更多的論點,但我希望解決方案適用於任何函數原型。

更新

很抱歉,但我認爲所有的答案做使用按值傳遞函數調用。它沒有實現關閉。他們把當前y值,並把它作爲函數參數和假設存在的y = 80setTimeout()後如下面的代碼

var y = 60; 
setTimeout(run, 20); 
y = 80; 

它打印Y = 60,而不是80內run()的聲明。我實際上想要保持y的參考,而不是像閉包那樣捕獲它的價值。謝謝

回答

2

你可以使用bind

var x = 45; 
var run = function(y){ 
     console.log(y); 
     console.log(x); 
}; 
function apple(){ 
    var y = 60; 
    setTimeout(run.bind(null, y), 20); 
} 
apple(); 
console.log(x); 

用於綁定的第一個參數是你要綁定到this什麼。之後,每個參數被傳遞給新創建的函數 - 注意我添加了y作爲run函數的參數。

bind給你的是一個帶有預定義上下文(this)的新函數,也可能是參數的默認值。

請注意儘管您應該始終避免這種情況。修改函數內部的外部變量永遠不是一個好主意,它會導致很多悲傷並過早地變灰。您應該嘗試重構代碼,以便您可以傳遞和返回值,而不依賴於引用或全局範圍的變量。

+0

對不起,但我不認爲上面的代碼通過引用捕獲。它實際上是通過價值獲取的。例如,假設setTimeout語句後有y = 80。 setTimeout處理程序打印60而不是80。 – user3205479

+0

此解決方案不適用於閉包。查看我更新的問題也非常感謝 – user3205479

+1

@ user3205479原始值總是按值傳遞。你所問的是不可能的。 – Schlaus

0

您的y變量不在run()的範圍內,所以您需要將其傳遞給run。您還可以通過運行作爲參數傳遞給apple(cb_fn)https://jsfiddle.net/stevenkaspar/ttxxpoof/

var x = 45; 
var y = 80; 
var run = function(){ 
    console.log('could be 80 or 85(depending on race condition): ' + y); 
    console.log('should be 45: ' + x); 
}; 

function apple(cb_fn){ 
    var y = 60; // you can declar var y again to have another ignore global y 
    setTimeout(function(){ 
    console.log('should be 60: ' + y); 
    cb_fn(); // this would be a callback function 
    }, 20); 
} 

apple(run); // you need to pass run in as a "callback" function 
console.log('should be 45: ' + x); 
y = 85; 
console.log('should be 85: ' + y); 
+0

看到我更新的問題謝謝 – user3205479

+0

您似乎正在設置一個競爭條件,這不是一個好主意。我已更新我的代碼 –

0

你可以用y中的相同你做X(設置它作爲一個全球性的)做的。

+0

請參閱我的更新問題謝謝 – user3205479

+0

對不起,但它打印60 – user3205479

+0

您將變量「y」設置爲全球範圍,請將其定義在Apple中。我知道如果它使全球變得可能,但我不想創建全局變量,如果蘋果有100個變量,那麼我需要使所有變量全局變量?提供正確的解決方案 – user3205479

相關問題