如何从JavaScript模块中的私有和公共函数访问公共属性?

时间:2017-03-23 21:23:35

标签: 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的私有变量来解决它,但我想知道如果没有它们我是否可以做到。

4 个答案:

答案 0 :(得分: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 :(得分:1)

在您使用它的方式中,您使用的名称变量是公共的,它与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();

答案 2 :(得分: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();

答案 3 :(得分:0)

this.name中的privateChangeNameToBobname设置为该功能的属性,而不是模块的属性。相反,您可以这样使用它:

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映射到的内容(例如,如果您尝试在内部使用{1}}内部使用this访问模块模块方法。