Показаны сообщения с ярлыком конструкторы. Показать все сообщения
Показаны сообщения с ярлыком конструкторы. Показать все сообщения

понедельник, 29 сентября 2014 г.

Три роли функций

Функции в JS могут использоваться в трёх ролях:

1. Собственно функции
2. Методы
3. Конструкторы

Функция-метод практически непригодна к использованию как обычная функция, особенно если использует this, т.к. в случае вызова вне контекста объекта this будет указывать на глобальный объект (или будет равен undefined в strict mode).

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

Конструктор при вызове с new неявно получает новый объект при вызове (на него ссылается this) и неявно возвращает новый объект, если return не используется в коде конструктора или же если return возвращает не объект.

Фактически, конструктор может вернуть произвольный объект любого типа, если в качестве аргумента оператора return будет использоваться объект:

mouse = { name: "Jerry", likesCheese: true, voice: function() { console.log("pi-pi-pi") } };

function Cat(name) {
    this.name = name;
    return mouse;
}

tom = new Cat("Tom");
tom.name;           // > "Jerry"
tom.voice();        // > pi-pi-pi
tom instanceof Cat; // > false

Одно из применений для подобного поведения - паттерн Singleton, позволяющий в конструкторе реализовать создание только единственного экземпляра объекта.

function Singleton() {

    if ( Singleton.instance ) {
        return( Singleton.instance );
    }
    return ( Singleton.instance = this );
 }

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

var a = new Singleton();
var b = new Singleton();

a === b; // > true

Во всех остальных случаях при создании объектов даже одного типа (даже пустых) они не являются равными.

var c = {}, 
    d = {};

c === d; // > false

суббота, 27 сентября 2014 г.

Объекты в JavaScript: Конструкторы


Для создания любого объекта можно использовать функцию конструктор вида:

function Cat(color, tail) {
    this._color = color;
    this._tail  = tail;
}

Фактически, конструктор является инициализатором свойств объекта. 
И затем создать конструктор при помощи оператора new.

var scratchy = new Cat("black", true);

Во время создания объекта контекст this устанавливается на созданный объект, а сам он возвращается в результате выполнения new, если не указано конкретное возвращаемое значение.

scratchy instanceof Cat; // > true

Методы объекта создаются через прототипы:

Cat.prototype.describe = function() {
    return this.color + " cat " + 
           (this._tail ? "with" : "without") + " tail";
}

Если забыть оператор new при создании объекта, то Cat выполнится как обычная функция, возвращающая значение undefined (return отсутствует) и устанавливающая значения _color и _tail для глобального объекта. Чтобы этого не произошло, конструктор желательно создавать с директивой "use strict"; которая выбросит исключение при попытке установки свойств глобального объекта.

Что можно предпринять против "забывчивости"?

1. Создание объекта можно перенести внутрь конструктора и тогда не понадобится использовать new при объявлении - это произойдет в коде конструктора:

function Cat(color, tail) {
    "use strict";

    if (this instanceof Cat) {
        this._color = color;
        this._tail = tail;
    } else {
        return new Cat(color, tail)
}

При вызове без new выполнение пойдёт сначала по ветви else, а потом уже с вновьсозданным объектом по ветви if