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

Каков современный способ структурирования "класса" в JavaScript?

Как создать "класс" (со свойствами и методами), на котором будет создано множество экземпляров?

4b9b3361

Ответ 1

В "современном" JavaScript существует три популярных метода определения объектов.

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

// Constructor, methods and members all rolled up into one definition
var Movie = function(name) {
    this.name = name;
    // Note that private members can be created using the closure property
    var _id = +(new Date());

    this.getName = function() {
        return this.name + " " + _id;
    };

    this.setName = function(name) {
        this.name = name;
    };
};

var m = new Movie("Beerfest");

Второй метод - это вариация и может быть взаимозаменяема с первым. Это также полезно для добавления новых методов к существующим объектам через свойство prototype. Частные члены и методы в этой форме невозможны.

// Constructor is separate from its methods
var Movie = function(name) {
    this.name = name;
}

Movie.prototype.getName = function() {
    return name;
};

Movie.prototype.setName = function(name) {
    this.name = name;
};

var m = new Movie("Kill Bill");

Третий метод заключается в использовании шаблона , который позволяет создавать объекты без использования оператора new.

var Movie = function (name) {
    var _id = +(new Date());
    var privateMethod = function() { alert(_id); };

    // All methods and members defined here are public
    return {
        name: name,
        getName: function() {
            return this.name + " " + _id;
        },
        setName: function(name) {
            this.name = name;
        }
    };
};

var m = Movie("Stackoverflow: the movie");

Обратите внимание, что в первом и третьем методах вы можете использовать частные члены доступа и методы. Но имейте в виду, что использовать this в частных методах, некоторые из которых должны произойти.

Ответ 2

// I like this pattern..

// class
function Person(name, birthdate) {
  this._name = name;
  this._birthdate = birthdate;
  /* should not do this
  * this.getAge = function() {
  * }
  * as the method will be constructed
  * for each instance, better to let it
  * be inherited from prototype, see below
  */
}

// class methods
Person.prototype.getBirthdate = function() {
  return this._birthdate;
}

// same as above, function as a method
Person.prototype.getAge = function() {
  var currentDate = new Date();
  // age in millis
  return currentDate - this._birthdate;
}

// the get age method can be a "static"
// method on the constructor function if you pass the
// person object
Person.getAge = function(person) {
  var currentDate = new Date();
  // age in millis
  //no reference to this
  return currentDate - person.getBirthdate();
}

// you could use it like this

myPerson = new Person("Steve", new Date("1980-01-01"));
// returns age in millis
myPerson.getAge();
// returns age in millis
Person.getAge(myPerson);

Вы также можете использовать анонимную функцию для моделирования частных и общедоступных

var PersonFactory = (function() {
  // private area, no one can alter
  // the person cache
  var _cache = {}

  // public area
  return {
    // returns a person born now
    getPerson: function(name) {
      if(_cache[name]) {
        return _cache[name];
      }
      else {
        _cache[name] = new Person(name, new Date());
        return _cache[name];
      }
    }
  }
})();

var p = PersonFactory.getPerson("Leif");
p.getAge();
p = PersonFactory.getPerson("Leif");
// should be the same age / obj
p.getAge();

Мне не нравится этот шаблон. Предупреждение подчеркивания _myVariable должно быть достаточно, чтобы пользователи из вашей библиотеки не использовали эти переменные/методы. Я использовал его, когда я впервые открыл его из-за моего фона Java. Это затрудняет работу с наследованием прототипов и может вызвать утечку памяти.

Ответ 3

Подход к объектной ориентации, наиболее свойственный JavaScript, заключается в использовании прототипного наследования, но существует много других шаблонов, включая псевдоклассическое наследование, которое имитирует шаблон наследования на основе классов на языках типа C и Java. Дуглас Крокфорд написал и сказал по этому вопросу и дает некоторые очень хорошие объяснения каждого из них. Взгляните на эти статьи:

Прототипное наследование в JavaScript

Классическое наследование в JavaScript

Ответ 4

JavaScript не использует классы так же, как Java, С++ или тому подобное.

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

function Foo(){ //vaguely like a Java constructor
    this.aField = 1; //define members simply by using 'this'
    this.aMethod = methodFunction; //assign a function as a member using 'this'
}

function methodFunction(){
}

var foo = new Foo(); //construct an object

Ответ 7

Используя анонимную функцию самоисполнения, вы можете разрешить публичные и частные атрибуты/методы.

Этот шаблон мне больше всего нравится:

(function ($, MyObject, undefined) {

    MyObject.publicFunction = function () {
        console.log("Public function");
    };

    var privateFunction = function () {
        console.log("Private function");
    };    

    var privateNumber = 0;
    MyObject.sayStuff = function () {
        this.publicFunction();
        privateFunction();
        privateNumber++;
        console.log(privateNumber);
    };  


    // You can even nest the namespaces
    MyObject.nestedNamespace = MyObject.nestedNamespace || {};
    MyObject.nestedNamespace.logNestedMessage = function () {
        console.log("Nested namespace function");
    };

}(jQuery, window.MyObject = window.MyObject || {}));

MyObject.sayStuff();
MyObject.sayStuff();
MyObject.nestedNamespace.logNestedMessage();
MyObject.publicFunction();

Узнал об этом из комментариев здесь и в этой статье.