2014-10-12 72 views
0

爲什麼我必須在閉包中聲明一個函數才能訪問閉包中的變量?我期望我能夠在閉包之外定義函數,但是可以在閉包周圍定義函數,提供它所需的變量,但變量不可用,除非函數實際上在閉包中定義。爲什麼我必須在閉包中定義一個閉包訪問變量時聲明一個函數?

http://jsfiddle.net/c5oba93a/1/

//reusable function defined outside of closure, I want to swap out myMethod within this function. 
var reusableFunction = function() { 
    //common code 
    try { 
     console.log(myVar); 
     myMethod.call(this); 
    } catch (e) { 
     console.log(e); 
    } 
    //common code 
}; 


var functOneForClosure = function() { 
    console.log('functOne'); 
}; 
var functTwoForClosure = function() { 
    console.log('functTwo'); 
}; 

//myMethod and myVar are undefined in reusableFunction 
(function() { 
    var myMethod = functOneForClosure; 
    var myVar = 'variable in closure with functOne'; 
    return reusableFunction; 
})()(); 
(function (myMethodIn) { 
    var myMethod = myMethodIn; 
    var myVar = 'variable in closure with functTwo'; 
    return reusableFunction; 
})(functOneForClosure)(); 

//if the function is defined within the closure it behaves as expected. 
var getReusableVersion =(function (myMethod) { 
    var myVar = 'defining function within closure makes the difference'; 
    return function() { 
     //common code 
     try { 
      console.log(myVar); 
      myMethod.call(this); 
     } catch (e) { 
      console.log(e); 
     } 
     //common code 
    }; 
}); 

getReusableVersion(functOneForClosure)(); 
+0

在函數內部聲明的var在這個函數之外是不可見的,並且在函數完成執行時被清除。 – 2014-10-12 10:27:57

+0

你在哪裏看到發生@MartinErnst? – pherris 2014-10-12 10:30:04

+0

有兩個IIFE定義'myVar'和'myMethod'並返回''reuasableFunction''然後執行。當IIFE的返回變量被清除時,因爲它們沒有被傳遞給'reusableFunction'。此外,在定義了'reusableFunction'的'地方',變量不是'可見的'。 – 2014-10-12 10:38:33

回答

1

@pherris根據您的beforelast評論:這不會幫助。 IIFE中的this指的是window對象,現在您可以使用其他屬性進行垃圾郵件了。但myVar and myMethod裏面的reusableFunction仍未定義,您必須改用this.myVarthis.myMethod。比垃圾郵件的窗口更好的是傳遞瓦爾作爲參數:

var reusableFunction = function (myVar, myMethod) { 
    // no try/catch needed anymore 
    console.log(myVar); 
    if (typeof myMethod == 'function') myMethod.call(this); 
    else console.log(myMethod); 
}; 

現在有兩種方式可以用你的IIFE調用它。

第一返回從與結合到其參數IIFE的函數並執行它算賬:

(function() { 
    var myMethod = functOneForClosure; 
    var myVar = 'variable in closure with functOne'; 

    // first argument of .bind() appears in the function as 'this', 
    // the others appear as fixed arguments of the function 
    return reusableFunction.bind(window, myVar, myMethod); 
})()(); 

第二種方式調用它的IIFE內側,從而該調用之後被移除:

(function() { 
    var myMethod = functOneForClosure; 
    var myVar = 'variable in closure with functOne'; 

    return reusableFunction(myVar, myMethod); 

    // of course its possible to call on 'this', but that doesn't change anything: 
    /* return reusableFunction.call(this, myVar, myMethod); */ 

})(); 
+0

這個交換的好處:範圍與上下文,IIFE的窗口範圍和關於.bind() - thx的提醒! – pherris 2014-10-12 17:11:45

相關問題