2016-06-24 3 views
0

Пример:Как объявить структуры данных на базовых объектах, чтобы они оставались независимыми в каждом расширенном объекте?

var Person = { 
 
    name : '', 
 
    collection : new Array(), 
 
    addToCollection : function(x) 
 
    { 
 
    this.collection.push(x); 
 
    }, 
 
    printCollection: function() { 
 
     console.log(this.collection); 
 
    } 
 
}; 
 

 

 
var skywalker = Object.create(Person); 
 
skywalker.name = 'Anakin Skywalker'; 
 
skywalker.addToCollection(1); 
 
skywalker.printCollection(); // prinnts [1] 
 

 

 
var skywalker2 = Object.create(Person); 
 
skywalker2.name = 'Anakin Skywalker 2'; 
 
skywalker.addToCollection(2); 
 
skywalker2.printCollection(); // prints [1, 2]

Я хотел бы достичь ситуации, в которой skywalker2.printCollection(); печатает [2]. Я хочу, чтобы базовый объект Person был связан с коллекцией и выставлял операции, такие как addToCollection (x).

+0

Очевидная ошибка: почему skywalker.addToCollection (2); попробуйте добавить его собственный объект skywalker2.addToCollection (2); –

+0

Затем вы должны добавить свойство 'collection' к самому инстанцированному объекту сразу после его создания с помощью объекта Object.create (Person)' и совместно использовать только функции для установки и получения ('addToCollection' и' setToCollection') в прототипе (объект 'Person' в этом случае) – Redu

+0

@AliTorabi благодарит за это, но это не меняет результат, однако @Redu В моем вопросе я сказал:« Я хочу, чтобы базовый объект Person был связан с коллекцией » , Под этим я подразумеваю, что я не хочу добавлять эту коллекцию в каждый экземпляр объекта. Разве нет способа добиться этого? –

ответ

1

Вы должны сделать это следующим образом;

var Person = { 
 
    name : '', 
 
    addToCollection : function(x) 
 
    { 
 
    this.collection.push(x); 
 
    }, 
 
    printCollection: function() { 
 
     console.log(this.collection); 
 
    } 
 
}; 
 
var sw1 = Object.create(Person), 
 
    sw2 = Object.create(Person); 
 

 
sw1.collection = new Array(); 
 
sw2.collection = new Array(); 
 
sw1.addToCollection(1); 
 
sw2.addToCollection(2); 
 

 
sw1.printCollection(); // <- 1 
 
sw2.printCollection(); // <- 2

Ну как за комментарием OP немного информации о создании объектов в JS. Object.create() позволит вам определить прототип объекта, и все, что в прототипе, используется совместно с экземплярами объектов. Поэтому в этом случае коллекционный массив является общим. Если вы не хотите делиться collection, вам просто нужно создать его в экземпляре объекта, как показано в предыдущем фрагменте. Однако, как я понимаю, вы этого не хотите. Хорошо, тогда есть еще один способ добиться этого. Мы можем иметь массив collection под функцией как частное свойство и получить доступ к нему путем закрытия через наши прототипы. Тогда мы добьемся того, чего хотим. Именно так;

function collectionInClosure(){ 
 
    var collection = [], 
 
    getCollection = function(){return collection}, 
 
    setCollection = function(v) {collection.push(v)}; 
 
    return { 
 
      printCollection: function() {console.log(getCollection())}, 
 
      addToCollection: setCollection 
 
     }; 
 
} 
 

 
var sw1 = Object.create(collectionInClosure()); 
 
    sw2 = Object.create(collectionInClosure()); 
 

 
sw1.addToCollection(1); 
 
sw2.addToCollection(2); 
 

 
sw1.printCollection(); // <- 1 
 
sw2.printCollection(); // <- 2

+0

В моем вопросе я сказал: «Я хочу, чтобы объект базового объекта был связан с коллекцией». Под этим я подразумеваю, что я не хочу добавлять эту коллекцию в каждый экземпляр объекта. Разве нет способа добиться этого? –

+0

@ Tomasz Szawara Обычно лучше сохранить свойства, которые вы не хотите использовать в создаваемом объекте, но так как вы не хотите, чтобы это был способ достижения вашей цели. Пожалуйста, см. Второй фрагмент, и мое объяснение добавлено в мой ответ. Оба объекта sw1 и sw2 полностью пусты. – Redu

+0

Да, и ваш расширенный ответ более уместен для моего первоначального вопроса, так как я только просил, чтобы коллекция обрабатывалась в базовом классе и отдельно для каждого экземпляра-объекта. То, что я действительно хотел, - это поведение, при котором все свойства являются общедоступными, но в то же время отдельными для каждого экземпляра, для которого мой ответ был подходящим. Однако я не смог точно описать его в своем вопросе. –

0

Его очень распространена практика, и большое удобство, чтобы иметь возможность абстрагироваться некоторые свойства в базовых классах, так что нам не нужно будет заботиться о них, когда инстанцировании или расширения объектов. Другие классически объектно-ориентированные языки, такие как Java, делают это для нас, и, как правило, они понимают более интуитивное поведение разработчиков.

Решение этой конкретной задачи может быть достигнуто двумя способами:

1) с ES6:

class Animal { 
 
    constructor(name) { 
 
    this.name = name; 
 
    this.collection = []; 
 
    } 
 
    addToCollection(x) { 
 
    this.collection.push(x); 
 
    } 
 
    printCollection() { 
 
    console.log(this.collection); 
 
    } 
 
} 
 

 
var dog = new Animal(); 
 
dog.addToCollection(1); 
 
dog.printCollection(); // prints 1 
 

 
var dog2 = new Animal(); 
 
dog2.addToCollection(2); 
 
dog2.printCollection(); // prints 2

Поскольку не все браузеры поддерживают ES6 (большинство браузеров имеют ES6 отключен по умолчанию), используйте Babel или аналогичный полиполк, чтобы иметь возможность использовать синтаксис выше.

Бабель будет использовать ES5 для эмуляции синтаксиса ES6 с JavaScript аналогично:

"use strict"; 
 

 
var _createClass = function() { 
 
    function defineProperties(target, props) { 
 
    for (var i = 0; i < props.length; i++) { 
 
     var descriptor = props[i]; 
 
     descriptor.enumerable = descriptor.enumerable || false; 
 
     descriptor.configurable = true; 
 
     if ("value" in descriptor) descriptor.writable = true; 
 
     Object.defineProperty(target, descriptor.key, descriptor); 
 
    } 
 
    } 
 

 
    return function(Constructor, protoProps, staticProps) { 
 
    if (protoProps) defineProperties(Constructor.prototype, protoProps); 
 
    if (staticProps) defineProperties(Constructor, staticProps); 
 
    return Constructor; 
 
    }; 
 
}(); 
 

 
var Animal = function() { 
 
    function Animal(name) { 
 
    // .. some Babel Class checks here 
 

 
    this.name = name; 
 
    this.collection = []; 
 
    } 
 

 
    _createClass(Animal, [{ 
 
    key: "addToCollection", 
 
    value: function addToCollection(x) { 
 
     this.collection.push(x); 
 
    } 
 
    }, { 
 
    key: "printCollection", 
 
    value: function printCollection() { 
 
     console.log(this.collection); 
 
    } 
 
    }]); 
 

 
    return Animal; 
 
}(); 
 

 
var dog = new Animal(); 
 
dog.addToCollection(1); 
 
dog.printCollection(); // prints 1 
 

 
var dog2 = new Animal(); 
 
dog2.addToCollection(2); 
 
dog2.printCollection(); // prints 2

2) Другой способ заключается в использовании ES5 синтаксис вдохновленный вавилонской подход:

var Person = function() { 
 

 
    function Person(name) { 
 
     this.name = name; 
 
     this.collection = []; 
 
     this.addToCollection = function (x) { 
 
      this.collection.push(x); 
 
     } 
 
     this.printCollection = function() { 
 
      console.log(this.collection); 
 
     } 
 
    }; 
 
    return Person; 
 
}(); 
 

 
var p1 = new Person(); 
 
p1.addToCollection(1); 
 
p1.printCollection(); // prints 1 
 

 
var p2 = new Person(); 
 
p2.addToCollection(2); 
 
p2.printCollection(); // prints 2

Посредством обертывания конструктора Лицом в выполняемой функции мы гарантируем, что новый конструктор создается каждый раз, когда кто-то создает экземпляр класса Person;