2014-02-05 80 views
0

我的問題是完全一樣的,因爲這一個Javascript revealing module pattern, public properties揭示的Javascript模塊模式和變量

在該線程,答案給出,但不是「爲什麼」。 。這是同樣的問題,用我自己的例子重申:

myApp.User = function() { 
    var firstName = 'Default', 
     lastName = 'Default'; 

    function setFirstName(name) { 
     firstName = name; 
    } 

    function setLastName(name) { 
     lastName = name; 
    } 

    function getFirstName() { 
     return firstName; 
    } 

    function getLastName() { 
     return lastName; 
    } 

    return { 
     getLastName: getLastName, 
     **getFirstName: getFirstName**, 
     setLastName: setLastName, 
     setFirstName: firstName 
    }; 
}; 

在這種情況下,用戶()的getFirstName總是evals到「默認」 - 即使我將其更改爲通過setFirstName功能的其他值。

如果我喜歡setFirstName取代:

return { 
    getLastName: getLastName, 
    **getFirstName: getFirstName**, 
    setLastName: setLastName, 
    setFirstName: firstName 
}; 

我能夠訪問更改值。我知道var firstName是通過值傳遞的,這就是爲什麼更新後的值沒有被反映出來。我不明白這個功能有什麼特別之處。指向函數中值的指針在哪裏?爲什麼所有功能「奇蹟般地」獲得更新(s)?

+2

如果「總是evals到‘默認’」那麼你就不會調用'setFirstName'第一的*同一個對象上*。此外,'{setFirstName:firstName}'意味着'obj.setFirstName' *不是一個函數(因爲'firstName' *不是函數),所以即使你想要,也不能調用它。 (並且由於代碼*不會改變* firstName變量..當然,它將始終是'默認'。) – user2864740

+1

可能重複[JavaScript封閉如何工作?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Philipp

+0

不應該將返回對象的最後一個屬性設置爲'setFirstName:setFirstName'而不是'setFirstName:firstname'? –

回答

0

指向函數中的值的指針在哪裏?

在函數的範圍 - 它包含所有可以訪問的變量。該訪問實際上使該功能成爲closure

爲什麼所有功能「奇蹟般」地獲取更新?

因爲所有功能共享變量聲明在一個更高的範圍。

+0

標記爲正確,因爲它是我的問題的核心。基本上我不明白關閉,所以這種行爲顯得怪異。 – user1821052

0

他們不會「奇蹟般地」獲取更新。他們裏面myApp.User這就是爲什麼他們可以訪問變量的位置。

當您做myApp.User().getFirstName()時,因爲getFirstName位於函數(scope)內部,所以它將能夠訪問此函數內部和此函數外聲明的變量。

function a(){ 
    var b = "hello"; 
    return { 
     setB: function(c){ b = c; }, 
     getB: function(){ return b; } 
    }; 
} 

var obj = new a(); 
obj.getB();   //hello 
obj.setB("new"); 
obj.getB();   //new 

在上面的例子中,getBsetB都住你的對象裏面,他們可以訪問a()範圍內的所有變量。

0

看看你做了什麼,在這裏你的第一個例子

setFirstName: firstName 

setFirstName不是功能「setFirstName」的引用,而是變「的firstName」 ......你沒有訪問函數'setFirstName'。該功能仍然無法使用,因此無法修改名字,就像你想要的那樣。

這是超出範圍 - 你沒有返回它,所以它可以用於外界,可以這麼說。它不在函數範圍的「外部」。返回函數(),並應用「setFirstName」,如下所示。

試試這個;

myApp.User = function() { 
    var firstName = 'Default', 
     lastName = 'Default'; 

    function setFirstName(name) { 
     firstName = name; 
    } 

    function setLastName(name) { 
     lastName = name; 
    } 

    function getFirstName() { 
     return firstName; 
    } 

    function getLastName() { 
     return lastName; 
    } 

    return { 
     getLastName: getLastName, 
     getFirstName: getFirstName, 
     setLastName: setLastName, 
     setFirstName: setFirstName 
    }; 
}(); 
myApp.User.setFirstName('bill'); 
myApp.User.getFirstName(); 
0
var User = function() { 
    var firstName = 'Default', 
     lastName = 'Default'; 

    return { 
     getLastName: function() { return lastName; }, 
     getFirstName: function() { return firstName; }, 
     setLastName: function(name) { lastName = name; }, 
     setFirstName: function(name) { firstName = name; }, 
     getName:  function() { return firstName + ' ' + lastName; } 
    }; 
}; 

var u = User(), 
    v = User(); 
console.log(u.getName() + ' - ' + v.getName()); 
// Outputs: 'Default Default - Default Default' 
u.setFirstName('Alice'); 
u.setLastName('Bob'); 
console.log(u.getName() + ' - ' + v.getName()); 
// Outputs: 'Alice Bob - Default Default'