7

EDIT: Я понял это из ответа Берги в конце.Как создать объект с частными членами, используя Object.create() вместо нового

Спасибо, Берги.

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

EDIT: Кажется, ответы на мой вопрос отключены по касательной. Я действительно не интересуюсь фабрикой и фактически не буду использовать, если. Мой вопрос касается частного государства. Из ответов и комментариев Берги я думаю, что могу что-то собрать.

Продолжение ...

EDIT: Берги начал отвечать на вопрос ниже, но оставил самую важную часть - личное состояние.

У меня было время подумать над идеей больше, но я все еще не могу достичь частного состояния, используя Object.create() без какой-либо фабрики. Но я хочу быть неправ, и Берги намекнул на решение ... Не стесняйтесь взять ответ Берги в качестве отправной точки.

ОРИГИНАЛ: Мои старания избегать 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/

Would init быть более идиоматических/подходящее название для метода factory?

Это безумие?

Be kind - javascript - это не мой первый язык.

+2

Почему вы не хотите использовать 'new'? –

+1

Douglas crockford. – bluekeys

+2

Это несчастливо. –

ответ

2

Да, метод инициализации на прототипе может быть более подходящим названием:

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

Однако, нет абсолютно никаких причин, чтобы не использовать классический конструктор с новым ключевым словом, которое элегантно сочетает в себе Object.create и init call.

Обратите внимание, что вы используете Object.create с абсолютно бесполезным. Ваш заводской шаблон (отлично действующий) возвращает хорошие объекты. Не нужно создавать новых объектов для каждого, которые наследуют от них. Вобще:

var instance = trackQueue.factory(); 

Если вам нравится звук имени методы «создать», вы можете использовать более идиоматическое имя для вашего завода:

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

EDIT: Ваша идея объединить фабричный шаблон с наследованием прототипов не так ошибочен. Тем не менее, прото-объект, из которого наследуются все наследуемые объекты, должен быть статичным, а не , создающим новый по каждому вызову.Ваш код может выглядеть следующим образом:

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(...); 
+0

Как настроить частные облачные области в функции init в вашем примере? – bluekeys

+0

Как обычно: используйте ключевые слова var или функции, и они будут привязаны к функции init. – Bergi

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. Обратитесь к this post за более удобным объяснением. This также является хорошим сообщением о предмете.

+0

Нет, вы ошибаетесь. Вы сделали ту же ошибку, что и OP: абсолютно нет необходимости использовать Object.create для объектов, зависящих от области видимости. – Bergi

+0

Я не могу понять, вы можете немного разъяснить? Не могу понять, почему его считают ошибкой. Я даже считаю ваш второй блок кода похожим на тот, который я написал, отличающийся тем, что ваш прототип является публичным участником фабрики. Я согласен с вашим подходом, если ваш заводский объект будет иметь больше публичных функций, кроме create(). – renatoargh

+0

Почему вы не возвращаете объектный литерал («personPrototype») напрямую? Какое использование Object.create в вашем коде? – Bergi