Подтвердить что ты не робот

Какой рекомендуемый способ создания объектов в NodeJS?

Я создаю композит для модуля request, однако я не уверен, что лучше всего подходит для создания объектов в JS для Node.

Вариант 1:

function RequestComposite(request) {
  return {
    get: function (url) { return request.get(url); }
  }
}
var comp = RequestComposite(request);
  • Примечание. Я знаю, что я должен назвать CB в асинхронном режиме, но для удобства объяснения я возвращаю его...

Вариант 2:

function RequestComposite(request) {
  this.request = request;
}

RequestComposite.prototype.get = function (url) { return this.request.get(url); };
var comp = new RequestComposite(request);

Вариант 3:

var RequestComposite = {
  init: function (request) { this.request = request; },
  get: function (url) { return request.get(url); }
}
var comp = Object.create(RequestComposite).init(request);

Я пытался найти свой путь, но я еще больше смутился о том, как использовать объекты...

Будет ли ответ другим, если я хочу использовать объекты для браузеров?

Спасибо.

4b9b3361

Ответ 1

Наиболее эффективный способ заключается в следующем:

  • Поместите всю необходимую инициализацию в конструктор (например, проверьте параметры конструктора, установите свойства и т.д.).

  • Установите методы в свойстве .prototype конструктора. Почему? Потому что это не позволяет переписывать каждый метод каждый раз, когда вы создаете объект. Таким образом вы перерабатываете один и тот же прототип для каждого создаваемого вами объекта. Эффективен в памяти и экономит время кодирования.

  • Не используйте закрытие для частной собственности. Почему? Он медленный и не позволяет использовать этот объект в цепочке наследования (псевдоприватные переменные не принадлежат объекту, они просто доступны). Вместо этого обычной практикой является использование подчеркивания при объявлении свойства объекта, чтобы указать, что это свойство _private, к которому нельзя обращаться извне.

  • Используйте new вместо Object.create. Проще запомнить, если вы привыкли к другим языкам ООП; и в конце new использует Object.create под капотом.

Другими словами, что-то вроде этого:

var Person = function (name) {
    this._name = name;
};

Person.prototype.sayHello = function () {
    alert('My name is: ' + this._name);
};

var john = new Person('John');
john.sayHello();

EDIT

Некоторая дополнительная информация:

  • Object.create vs new. Тест здесь. Хотя вопрос к Node.js, я думаю, что такое же поведение следует ожидать. (любые исправления приветствуются)

  • Замыкания для эмуляции частных свойств. Вы можете прочитать о в этом вопросе.. То, что свойства private/closure не принадлежат объекту, является фактом программирования: они доступны для методов объекта, но не принадлежат объекту. При использовании наследования это большой беспорядок. Кроме того, только методы, которые объявлены в конструкторе, имеют доступ к замыканию. Методы, определенные в прототипе, отсутствуют.

  • Определение методов в конструкторе или свойстве прототипа: прочитайте этот вопрос и посмотрите этот тест

ОБНОВЛЕНИЕ 15/04/2016

Точки, которые я высказал здесь три года назад, все еще верны с точки зрения производительности, но мое мнение о том, что такое "рекомендуемый путь", за это время немного изменилось. Фабричные функции в целом являются хорошим вариантом, который будет первым подходом OP. Просто пример:

function Person(name) {
    return {
        sayHello: function () { alert('My name is: ' + name); }
    };
}

а затем просто сделайте:

var p = Person('John');

В этом случае вы торгуете гибкостью (без связи new, простотой компоновки с другими "дополнениями") и простотой (без путаницы this, легким созданием объектов) для некоторой скорости и памяти. В целом они совершенно действительны. Если у вас есть проблемы с производительностью, и это из-за этого способа создания объектов, вернитесь к другому методу. Подход Object.create также хорош, он как-то падает в середине new и заводских функций (примечание: новый синтаксис class является синтаксическим сахаром для new + prototype)

Подводя итог: мой рекомендуемый способ - начать с самого простого и простого способа создания объектов (фабричные функции), а затем перейти к другим методам, когда вы сталкиваетесь с проблемами производительности (чего в большинстве случаев никогда не бывает).

Ответ 2

Существует множество способов создания "классов" и "объекта" в JS. Я предпочитаю этот путь:

var MyObject =
        function(args) {
            // Private
            var help = "/php/index.php?method=getHelp";
            var schedule = "/php/index.php?method=getSchedules";
            var ajax = function(url, callback, type) {
                //....
            }

            // Public
            this.property = 0;
            this.getInfo = function() {
                // ... 
            }

            // Constructor
            function(data) {
               this.property = data;
           }(args);
        };

var o = new MyObject();

Ответ 3

Примечание. Если вы более знакомы с синтаксисом ООП, вы также можете использовать class, который является просто синтаксическим сахара над существующим прототипом.

Сравнение производительности между четырьмя способами создания объекта - с конструктором (Chrome 61 - https://jsperf.com/create-object-ways)

Вариант A: Использование return (Самый быстрый 3x)

Вариант B: Использование {key:value} (1.5x)

Вариант C: Использование prototype (1x) < - Base

Вариант D: Использование class (1.02x)

Вариант A лучше всего работает. Обратите внимание, что некоторые из повышения производительности - это то, что он избегает использования new или object.create. Чтобы просто провести справедливое судебное разбирательство, вот еще один тест между объектами только для метода без конструктора и свойств.


Сравнение производительности между четырьмя способами создания объектов только для методов (Chrome 61 - https://jsperf.com/create-static-object-ways)

Вариант A: Использование return (3.2x)

Вариант B: Использование {key:value} (Самый быстрый 3.3x)

Вариант C: Использование prototype (1.8x)

Вариант D: Использование class (1.9x)

Вариант B немного опередил вариант A. Кроме того, узкое место, вызванное object.create, было больше new.


Лучшая практика

Вариант A (с использованием return) лучше всего работает в обоих сценариях. Этот способ может стать немного беспорядочным, если у вас много методов и свойств.

Я предпочитаю разделить конструктор и свойства в отдельном объекте, используя Вариант A и методы в другом объекте, используя Вариант B. Этот подход требует отправки дополнительной ссылки instance в параметрах, но может быть полезен, если у вас есть несколько объектов, использующих одни и те же свойства и конструктор. (Некоторое наследование ООП также может быть достигнуто).

Пример:

// Constructor & Properties Object (Using option A)
var UserData = function(request){

  // Constructor
  if ( request.name )
    var name = request.name;
  else
    var name = 'Not Available';

  if ( request.age )
    var age = request.age;
  else
    var age = null;


  // Return properties
  return {
    userName: name,
    userAge: age
  };

};


// Object methods (Using Option B)
var Adults = {

  printName: function(instance){ // Read propery example
    console.log( 'Mr. ' + instance.userName );
  },

  changeName: function(instance, newName){ // Write property example
    instance.userName = newName;
  },

  foo: function(){
    console.log( 'foo' );
  }

};


// Object methods (Using Option B)
var Children = {

  printName: function(instance){
    console.log( 'Master ' + instance.userName );
  },

  bar: function(){
    console.log( 'bar' );
  }

}


// Initialize
var userData = UserData ( {name: 'Doe', age: 40} );

// Call methods
Adults.printName(userData); // Output 'Mr. Doe'
Children.printName(userData); // Output 'Master Doe'

Adults.foo(); // Output 'foo'
Children.bar(); // Output 'bar'

Adults.changeName(userData, 'John');
Adults.printName(userData); // Output 'Mr. John'