简体   繁体   English

从JavaScript构造函数返回一个对象(避免使用“ new”)时,如何实现公共成员?

[英]When returning an object from a JavaScript constructor function (avoiding 'new') how do I implement public members?

I have begun writing my 'class' type JavaScript functions like the Module Pattern or Revealing Module patten. 我已经开始编写“类”类型的JavaScript函数,例如模块模式或显示模块样式。 This avoids the use of 'new' and allows me to define which functions are public in a single place. 这避免了使用“新”功能,并允许我定义在单个位置公开的功能。 However, I have been unable to see how to use and access public data members in this pattern. 但是,我无法看到如何以这种模式使用和访问公共数据成员。

eg the member 'id' below is accessible through myobj.getId(), but myobj.id is undefined. 例如,下面的成员“ 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;}
    }
}

Is there no way to get myobj.id to work returning the value that was set in initialize()? 有没有办法让myobj.id能够返回在initialize()中设置的值?

Your problem is that you aren't taking advantage of closure. 您的问题是您没有利用封闭。 The line id:id creates a new variable as a member of the object literal you are returning. id:id行将创建一个新变量作为您要返回的对象文字的成员。 This has the default value undefined . 默认值为undefined Then you are assigning the same variable id back to itself, undefined again. 然后,您将向其自身分配相同的变量id ,再次undefined

Also, a module is a single object instance, not a factory function. 此外,模块是单个对象实例,而不是工厂功能。 Try something like this: 尝试这样的事情:

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
});

The core of the module pattern is a self executing anonymous function that declares variables and then returns an object that has privileged access to those variables through closure . 模块模式的核心是一个自执行的匿名函数,该函数声明变量,然后返回一个对象,该对象可以通过闭包来特权访问这些变量。

The extra parens at the end, here containing an object literal with some options that get passed in, executes the function, which then returns an object and assigns it to myModule . 最后的多余部分(其中包含一个带有一些传入选项的对象文字)执行该函数,然后该函数返回一个对象并将其分配给myModule

Anything declared as a member of that returned object can be accessed publicly. 声明为该返回对象成员的任何内容都可以公开访问。 Code in the returned object has access to the variables defined in the anonymous function through closure even after the function has returned. 返回的对象中的代码即使关闭,也可以通过闭包访问匿名函数中定义的变量。 The variables declared in the anonymous function are effectively private. 匿名函数中声明的变量实际上是私有的。 Code outside the function cannot address them except through the methods provided in the returned object. 函数外的代码无法解决它们,除非通过返回的对象中提供的方法。

The whole thing results in a single object instance in myObject . 整个过程导致myObject中有一个对象实例。 No more than one can be created, which is the definition of a module. 最多只能创建一个,这是模块的定义。 A similar approach could be taken the create a factory function however. 但是,可以采用类似的方法来创建工厂功能。

The reason is that your variable id is set to undefined by default and it's type will be undefined as well. 原因是您的变量id默认情况下设置为undefined ,并且其类型也将为undefined Now, because undefined type is a primitive one your assignment in the returned object will be a value assignment, not reference. 现在,由于未定义类型是一种原始类型,您在返回对象中的赋值将是值赋值,而不是引用。 So obj.id will become undefined in the instance and not the same as the id variable in the constructor function. 因此, obj.id将在实例中变为undefined ,并且与构造函数中的id变量不同。

Now initialize will change the id in the constructor function, and getId will return the same id , but obj.id will refer to the undefined object property. 现在, 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; }
    }
}

Run the whole stuff to see it works as expected. 运行全部内容以查看其是否按预期工作。

You can solve this and still maintain the syntactic sugar of the Revealing module pattern by returning a cached object instead of an anonymous one. 您可以解决此问题,并通过返回一个缓存的对象而不是一个匿名对象来保持Revealing模块模式的语法糖。

eg: 例如:

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;
}());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM