7

编辑:我最终从Bergi的回答中弄清楚了。

谢谢伯吉。

pubPrivExample = (function () {
    return {
        init : function () {
            var private;

            this.setPrivate = function (p) {
                private = p;
            };
            this.getPrivate = function () {
                return private;
            };
        },

        public : "This is public\n"
    };
}());

var a;

a = Object.create(pubPrivExample);
a.init();
a.setPrivate("This is private");

document.write(a.getPrivate());

编辑:看来我的问题的答案是不相干的。我真的对工厂不感兴趣,实际上宁愿不使用 if。我的问题是关于私人国家的。从 Bergi 的回答和评论中,我想我可以把一些东西放在一起。

待续...

编辑:Bergi 已经开始回答下面的问题,但忽略了最重要的部分——私有状态。

我有时间更多地考虑这个想法,但是如果没有某种工厂,我仍然无法使用 Object.create() 实现私有状态。但我想错了,Bergi 提到了一个解决方案......随意以 Bergi 的回答为起点。

原文:我对避免new使用 javascript 的追求将我带到了一个特殊的地方。我想要私有对象成员,但我不想放弃Object.create()

这是代码。

var trackQueue = {};

trackQueue.factory = function () {
    var that, queue;
    that = this;
    queue = [];

    that.push = function (item) {
        queue.push(item);
    };

    that.work = function () {
        document.write(queue + "<br />");
    };

    return {
        work : that.work,
        push : that.push
    };        
};

var a = Object.create( trackQueue.factory() );
a.push("a");
a.push("b");
a.push("c");

var b = Object.create( trackQueue.factory() );
b.push("d");
b.push("e");
b.push("f");

a.work();
b.work();

还有一个jsfiddle

http://jsfiddle.net/dsjbirch/Wj6cp/10/

该方法会init是一个更惯用/更合适的名称factory吗?

这是疯了吗?

友善点 - javascript 不是我的第一语言。

4

2 回答 2

2

是的,原型上的 init 方法可能是更合适的名称:

var proto = {
    init: function(args) {
        // setting up private-scoped vars,
        var example = args;
        // privileged methods
        this.accessPrivate = function(){ return example; };
        // and other stuff
        this.public = 5;
    },
    prop: "defaultvalue",
    ...
}

var instance = Object.create(proto);
instance.init();

但是,绝对没有理由不使用带有 new 关键字的经典构造函数,它优雅地结合了Object.createandinit调用。

请注意,您使用Object.create的是绝对没有用的。您的工厂模式(完全有效的应用)返回好的对象。无需为从它们继承的每个对象创建新对象。做就是了:

var instance = trackQueue.factory();

如果您喜欢方法名称“create”的声音,您可以为您的工厂使用更惯用的名称:

trackQueueFactory.create = function(args) {...};

编辑:您将工厂模式与原型继承相结合的想法并没有那么错误。然而,所有制造对象继承的原型对象需要是静态的,而不是在每次调用时创建一个新对象。您的代码可能如下所示:

var factory = {
    proto: {
        ...
    },
    create: function(args) {
        var product = Object.create(this.proto);
        // set up private vars scoped to the create function
        // privileged methods
        product.doSomethingSpecial = function(){ ... };
        // and other stuff
    }
};

var a = factory.create(...);
于 2012-06-28T22:30:11.020 回答
2

我认为这是实现您的要求的明确方法:

var personFactory = function(id, name, age){
    var _id = id;
    var _name = name;
    var _age = age;

    var personPrototype = {
        getId: function(){
            return _id;
        },
        setId: function(id){
            _id = id;
        },
        getName: function(){
            return _name;
        },
        setName: function(name){
            _name = name;
        },
        getAge: function(){
            return _age; 
        },
        setAge: function(age){
            _age = age;
        },
        work: function(){
            document.write(this.toString());
        },
        toString: function(){
            return "Id: " + _id + " - Name: " + _name + " - Age: " + _age;
        }
    };

    return Object.create(personPrototype);
};

用法:

var renato = personFactory(1, "Renato Gama", 25);
console.log(renato.getName()); //logs "Renato Gama"
renato.setName("Renato Mendonça da Gama");
console.log(renato.getName()); //logs "Renato Mendonça da Gama"

如果我没记错的话,这是 MODULE PATTERN 的用法之一。请参阅这篇文章以获得更好的解释。也是一篇关于这个主题的好帖子。

于 2012-07-02T04:53:28.217 回答