2017-03-23 81 views
2

我想知道如何從JavaScript模塊中的私有和公共函數訪問公共屬性?如何從JavaScript模塊中的私有和公共函數訪問公共屬性?

例如,如果這是我的模塊:

var PersonModule = (function(){ 

    var sayHello = function(){ 
     alert("Hello " + name); 
    } 

    var privateChangeNameToBob = function(){ 
     this.name = "Bob"; 
    } 

    var changeName = function(){ 
     privateChangeNameToBob(); 
    } 

    return { 
     name: "", 
     sayHello: sayHello, 
     changeName: changeName 
    } 
})(); 

無論sayHellochangeName功能正常工作,因爲我不知道如何訪問公共name財產。有沒有辦法做到這一點?我已經通過使用私有變量與getter和setter一起解決了這個問題,但是我想知道如果沒有它們,我可以做到這一點。

+0

凡的名字被宣佈?它是一個全局變量嗎?你可以在jsfiddle的片段中發佈更多的代碼,以便我們可以更全面地瞭解你正在嘗試做什麼? –

回答

5

您需要的結果對象的引用:

var PersonModule = (function(){ 
    function sayHello() { 
     alert("Hello " + person.name); 
    } 
    function privateChangeNameToBob() { 
     person.name = "Bob"; 
    } 
    function changeName() { 
     privateChangeNameToBob(); 
    } 

    const person = { 
     name: "", 
     sayHello, 
     changeName 
    }; 
    return person; 
})(); 

當然,鑑於你的單身IIFE模塊,你也可以同樣是指PersonModule.name直接。

+1

'sayHello'仍然引用一個未定義的'name'。它也應該更改爲'person.name'。 –

0

您需要在閉包中聲明屬性。檢查這個例子,以便更好地理解它:

var ClassName = function(constructorParam) { 
  
    var privateProperty = 'Im a private property'; 
    this.publicProperty = 'Im a public property'; 
  
    function privateMethod() { 
     console.log('Private method'); 
    } 
  
    this.publicMethod = function() { 
     console.log('Public method'); 
     // We can call private properties 
     console.log(privateProperty); 
     // Either private methods 
     privateMethod(); 
    } 
  
} 
  
var instance = new ClassName('Here goes something to constructor'); 
instance.publicMethod(); 
0

this.nameprivateChangeNameToBob被設置name作爲函數的一個屬性,而不是模塊。你可以,而是使用它像這樣:

var PersonModule = (function(){ 
    var name = ''; 
    //... 
    var privateChangeNameToBob = function(){ 
     name = "Bob"; 
    } 
    return { 
     name: name, 
     sayHello: sayHello, 
     changeName: changeName 
    }; 
})(); 

見小提琴這裏:最後https://jsfiddle.net/yv8uqh5y/

一筆記可能對你有用的設計模式。你可以聲明你的模塊範圍內命名base或類似的變量,就像這樣:

var PersonModule = (function(){ 
    var base = {}; 

    base.name = ''; 

    base.sayHello = function() {/* ... */}; 
    //... 

    return { 
     name: base.name, 
     sayHello: base.sayHello, 
     changeName: base.changeName 
    }; 
})(); 

見小提琴這裏:https://jsfiddle.net/k63u9bfo/

這樣,你可以參考你的模塊的基礎,而不必擔心什麼this地圖(例如,如果你試圖在內部使用this在模塊方法中聲明的匿名函數內訪問模塊

+0

好信息,但'changeName'函數仍然不會將名稱更改爲「Bob」。你知道爲什麼嗎? – jabe

+0

在IIFE中使用'this'將引用全局對象。這不是你想要的。 – Bergi

+0

@jabe我更新了我的答案。在'changeName'的上下文中,'this'基本上是將'name'設置爲'changeName'的屬性,而不是模塊。 –

1

以你使用的方式,你使用的名稱變量是public和你sayHello中的一樣 方法。你必須明白,這是一個MODULE,而不是一個需要實例化的類。 IIFE已經爲你實例化它。要做你想做的事,你可以使用下面的模型。在公共方法/變量中使用self.,私有中沒有任何內容。然後它將全部工作。

var PersonModule = (function(){ 
 
    var self = {}; 
 

 
    var privateChangeNameToBob = function(){ 
 
     self.name = "Bob"; 
 
    }; 
 

 
    self.sayHello = function(){ 
 
     console.log("Hello " + self.name); 
 
    }; 
 

 
    self.changeName = function(){ 
 
     privateChangeNameToBob(); 
 
    }; 
 

 
    self.name = ""; 
 
    
 
    return self; 
 
})(); 
 

 

 
PersonModule.name = 'Test'; 
 
PersonModule.changeName(); 
 
PersonModule.sayHello();

+1

不,它不*工作時,你打電話' changeName()' – Bergi

+0

已更正,感謝您的關注。 –