揭示模块模式、公共变量和返回语句

6
我正在尝试理解 (揭示)模块模式 中的 公共属性 如何工作。 卡尔·丹利 "揭示模块模式" 指出的一个优点是:

明确定义的公共方法和变量,提高可读性

让我们来看一下这个代码(fiddle):
var a = function() {
    var _private = null;
    var _public = null;
    function init() {
        _private = 'private';
        _public = 'public';
    }
    function getPrivate() {
        return _private;
    }
    return {
        _public : _public,
        init : init,
        getPrivate : getPrivate,
    }
}();

a.init();
console.log( a._public ); // null
console.log( a.getPrivate() ); // "private"

当调用时,它返回null。现在我可以操作该公共属性,例如a._public ='public';,但我无法从我的对象内部更改它。或者至少这些更改不会传递。我有点期望它是"public",因为它在init方法之前被更新了。

这是否意味着我不能有任何处理公共属性的方法?那么,在此模式中使用公共属性就没有什么意义了,对吗?我也尝试过这个但并没有成功(fiddle):

return {
    _pubic : _public,
    init2 : function() {
        _public = 'public';
    }
}

最后,我有一个关于整个return语句的问题。为什么不能只使用return this;来使所有内容都公开?因为this应该是自调用函数的上下文,它不应该返回其中的所有内容吗?为什么我必须创建另一个被返回的对象?在这个fiddle中,它返回了window对象。

3个回答

9

这是否意味着我不能有任何处理公共属性的方法?

不,它意味着您不能拥有公共变量var _public是一个变量,它无法从外部访问,当您修改私有变量时,这不会反映在您的公共._public属性中。

如果您想使事情公开,请使用属性:

var a = function() {
    var _private = null;
    function init() {
        _private = 'private';
        this._public = 'public';
    }
    function getPrivate() {
        return _private;
    }
    return {
        _public : null,
        init : init,
        getPrivate : getPrivate,
    }
}();

我可以操纵公共属性,如 a._public = 'public';。但我无法从我的对象内部更改它。
您可以在对象的方法中使用this,如上所示。或者您可以使用a来引用该对象,甚至可能存储对您返回的对象的本地引用。有关差异,请参阅此处
或者至少这些更改没有传递。
是的,因为变量与属性不同(与某些其他语言(如Java)不同,并且全局变量除外)。当您在对象文字中导出public: _public时,它仅从_public变量中获取当前值并在对象上创建一个属性。变量没有持久引用,对其进行的更改不会反映在另一个变量中。
为什么不能只使用return this;使所有内容都公开?因为这应该是自调用函数的上下文,所以它不应该只返回其中的任何内容吗?
变量是JavaScript中作用域的一部分。(除了全局作用域外)这些作用域不是语言可访问的对象。 this关键字不是指函数作用域,而是指调用时提供的上下文。这可以是方法调用中的基础引用,构造函数调用中的新实例,或者在像您的基本函数调用中没有任何东西(或松散模式下的全局window对象)。

非常感谢您简明扼要且有益的解释。 - lampshade
1
@T.J.Crowder:谢谢你的信任 :-) 实际上,我在发布这个存根后就去吃午饭了,看到你已经回答了...不幸的是,你已经删除了你的答案,它的内容甚至没有被保留在历史记录中 :-/ - Bergi
是的,我也看到了他的回答,其中有一些不错的见解。但突然间它就消失了。 - lampshade

6

在您的模块定义中,_public是按值复制的,因为在JavaScript中,只有对象被分配为引用。之后,它与本地的 _public 变量完全没有关联。因此,只有当您将 _public "装箱"成一个对象,以便通过引用复制它,或者您还在模块内部引用对象的属性时,才能使其起作用,并且只有一个对本地变量的引用:

var a = function() {
    var module = {
        _public: null
    };

    // use module._public here 

    return module;
}();

a._public = "foo";

似乎将事物封装成对象是一个很酷的技巧。谢谢。 - lampshade

0

您可以使用此结构来创建新类

function a(){
    var _private = null;
    this.public = null;
    this.getPrivate = function(){
        return _private;
    };

    function init(){
        _private  = "private";
        this.public = "public";
    }

    init.apply(this, arguments);
}

//static function
a.create = function(){
    return new a();
};

//using
var b = new a();
//or
var b = a.create();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接