2

我已经开始编写我的“类”类型 JavaScript 函数,例如 Module Pattern 或 Revealing Module patten。这避免了使用“新”,并允许我在一个地方定义哪些函数是公共的。但是,我一直无法看到如何在这种模式下使用和访问公共数据成员。

例如,下面的成员“id”可通过 myobj.getId() 访问,但 myobj.id 未定义。

function setup(){
    var myobj = MyObject();
    myobj.initialize();
    alert(myobj.getId()); // returns 3, as expected
    alert(myobj.id); // returns undefined
}
function MyObject(){
    var id;
    function initialize(){
        //do some stuff that initializes data including...
        id = 3;
    }
    return{
        initialize:initialize,
        id:id,
        getId:function(){ return id;}
    }
}

有没有办法让 myobj.id 返回在 initialize() 中设置的值?

4

3 回答 3

3

你的问题是你没有利用关闭。该行id:id创建一个新变量作为您要返回的对象文字的成员。这具有默认值undefined。然后,您再次将相同的变量分配id回自身undefined

此外,模块是单个对象实例,而不是工厂函数。尝试这样的事情:

var myModule = (function(opts) {
    var foo = opts.foo || 0,    //private variables with default values
        bar = opts.bar || 0,    // if none are passed in

        product = function() {      //private method
            return (foo * bar);
        };

    return {
        getFoo : function() {   //public methods
            return foo;
        },
        fooTimesBar : function() {
            return product();
        }
    }
})({
    foo : 5,                    //options object
    bar : 7
});

模块模式的核心是一个自执行匿名函数,它声明变量,然后返回一个对象,该对象通过闭包获得对这些变量的特权访问。

最后的额外括号,这里包含一个带有一些传入选项的对象文字,执行该函数,然后返回一个对象并将其分配给myModule.

任何声明为该返回对象的成员的东西都可以公开访问。即使在函数返回之后,返回对象中的代码也可以通过闭包访问匿名函数中定义的变量。在匿名函数中声明的变量实际上是私有的。函数外的代码只能通过返回对象中提供的方法来处理它们。

整个事情在myObject. 最多只能创建一个,这是一个模块的定义。然而,可以采用类似的方法来创建工厂函数。

于 2010-07-15T18:17:36.787 回答
1

原因是您的变量默认id设置为,并且它的类型也是如此。现在,因为未定义类型是原始类型,所以您在返回对象中的赋值将是值赋值,而不是引用。所以会变成实例中和构造函数中的变量不一样。undefinedundefinedobj.idundefinedid

现在initialize将更改id构造函数中的 ,并getId返回相同的id,但obj.id将引用undefined对象属性。

function MyObject(){
    // initialize is used as a public function so
    // this will always refer to the current instance
    function initialize(){
        this.id = 3;
    }
    return {
        // no need to define id here it will 
        // report undefined on access by default
        initialize: initialize,
        getId:function(){ return this.id; }
    }
}

运行整个东西以查看它是否按预期工作。​</p>

于 2010-07-15T16:45:12.867 回答
0

您可以通过返回缓存对象而不是匿名对象来解决这个问题,并且仍然保持 Revealing 模块模式的语法糖。

例如:

NAMESPACE.Module = (function () {

    //All public members go on api
    var api = {}
    api.id = 3;

    //Private members
    var self,
        foo,
        bar;


    /**
        @public
    */
    api.init = function () {
        self = this;
        console.log(this); //NAMESPACE.Module
    }


    /**
        @private
    */
    function _privateFunction() {
        console.log(self); //NAMESPACE.Module
    }

    return api;
}());
于 2012-05-25T09:25:16.910 回答