Три способа определить класс в JavaScript

С точки зрения синтаксиса, JavaScript очень гибкий объектно-ориентированный язык программирования. В этой статье вы найдете 3 способа определить и создать экземпляр объекта. И даже если вы уже выбрали себе предпочтительный метод, знание альтернатив поможет разобраться в чужом коде.

Важно отметить, что в JavaScript нет классов. Чтобы имитировать функционал классов могут быть использованы функции, но в целом JavaScript - бесклассовый язык. Все является объектом. И когда дело доходит до наследования, то объекты наследуют от объектов, а не классы от классов, как в "класс"-ических языках.

1. Используем функцию

Это, вероятно, один из наиболее часто используемых вариантов. Вы определяете обыкновенную функцию в JavaScript, и создаете объекты используя ключевое слово new. Чтобы определить свойства и методы объекта, созданного при помощи function() используется ключевое слово this, как видно из примера ниже.

function Apple (type) {
    this.type = type;
    this.color = "red";
    this.getInfo = getAppleInfo;
}
 
// антипаттерн! читайте ниже...
function getAppleInfo() {
    return this.color + ' ' + this.type + ' apple';
}

Чтобы создать экземпляр объекта используя функцию-конструктор Apple, установить некоторые свойства и вызвать методы вы можете сделать следующее:

var apple = new Apple('macintosh');
apple.color = "reddish";
alert(apple.getInfo());

1.1. Определяем методы внутри объекта

В приведенном выше примере вы видите, что метод getInfo() "класса" Apple был определен в виде отдельной функции getAppleInfo(). И, хотя этот метод отлично работает, у него есть один большой недостаток - в итоге вы получите кучу таких функций, и все они будут в глобальном пространстве имен. Это значит, что вы можете получить конфликт имен, если вы (или другая, используемая вами библиотека) определите еще одну функцию с таким же именем. Чтобы избежать загрязнения глобального пространства имен, методы можно определять внутри функции-конструктора, вот так:

function Apple (type) {
    this.type = type;
    this.color = "red";
    this.getInfo = function() {
        return this.color + ' ' + this.type + ' apple';
    };
}

Используя этот синтаксис, вам ничего не нужно менять методы создания экземпляра объекта и его использования.

1.2 Добавляем методы к прототипу объекта

Недостаток пункта 1.1 в том, что метод getInfo() создается заново каждый раз, когда вы создаете новый объект. Иногда это именно то, что вам нужно, но такие ситуации достаточно редки. Менее ресурсоемкий вариант - добавить getInfo() к прототипу функции конструктора.

function Apple (type) {
    this.type = type;
    this.color = "red";
}
 
Apple.prototype.getInfo = function() {
    return this.color + ' ' + this.type + ' apple';
};

И опять, вы можете использовать новые объекты точно так же, как и в пункте 1. и 1.1.

2. Используем литералы объектов

Литералы - более короткий способ определения объектов и массивов в JavaScript. Чтобы создать пустой объект, выполните var o = {}; вместо "обычного" var o = new Object();.

В случае с массивами вы можете выполнить var a = []; вместо var a = new Array();.

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

var apple = {
    type: "macintosh",
    color: "red",
    getInfo: function () {
        return this.color + ' ' + this.type + ' apple';
    }
}

В этом случае вам не нужно (да вы и не можете) создавать экземпляр класса, он уже существует. Так что вы просто начинаете использовать созданный объект.

apple.color = "reddish";
alert(apple.getInfo());

Такие объекты иногда называют синглтонами. В классических языках, вроде Java, синглтон означает, что в любое время вы можете иметь только один экземпляр этого класса, повторное создание объектов того же класса невозможно. В JavaScript (классов нет, помним?) эта концепция лишена смысла, так как все объекты синглтоны по-умолчанию.

3. Синглтон с использованием функции

И снова синглтон, да? :)

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

var apple = new function() {
    this.type = "macintosh";
    this.color = "red";
    this.getInfo = function () {
        return this.color + ' ' + this.type + ' apple';
    };
}

Как вы видите, это очень напоминает метод в пункте 1.1, описанном выше, но сам объект используется в точности как описано в 2.

apple.color = "reddish";
alert(apple.getInfo());

new function(){...} делает одновременно два дела: определяет функцию (анонимная функция-конструктор) и вызывает её при помощи new. Это может сбивать с толку, если вы не привыкли использовать подобные конструкции, и в целом, используется не так уж и часто, но это один из вариантов на случай, когда вам действительно нужна функция-конструктор, которая будет использована один раз и нет никакого смсыла давать ей имя.

Итоги

Вы увидели три (плюс один) способа создания объектов в JavaScript. Помните, что (вопреки заголовку статьи) в JavaScript нету такой вещи, как "класс".

Оригинал статьи на английском.