При вызове с оператором new функция-конструктор всегда возвращает объект. По умолчанию это объект, на который указывает ссылка this. Если внутри конструктора к нему не добавляются никакие свойства, возвращается "пустой" объект ("пустой", если не считать свойства и методы, унаследованные от прототипа конструктора). Конструкторы неявно возвращают значение this, даже если в них отсутствует инструкция return. Однако сохраняется возможность вернуть любой другой объект по своему усмотрению. Стоит помнить, что если вызвать конструктор без оператора new, ссылка this будет указывать на глобальный объект. В браузерах ссылка this будет указывать на объект window. Если в конструкторе создается какое-либо новое свойство, такое как this.member, то при вызове конструктора без оператора new будет создано новое свойство глобального объекта, к которому можно будет обратиться так: window.member или просто member. Чтобы этого избежать нужно использовать конструктор иначе.
function Person(name) {
var that = {};
that.name = name || '';
return that;
}
Но в этом случае будет утрачена связь с прототипом, поэтому все члены, добавленные к прототипу функции Person, окажутся недоступными для объектов. Чтобы этого избежать, нужно немного видоизменить конструктор:
function Person(name) {
if (!(this instanceof Person)) {
return new Person(name);
}
this.name = name || '';
}
Person.prototype.getName = function () {
return this.name;
};
var Darvin = Person('Darvin');
console.log(Darvin.getName()); // Darvin
var Einstein = new Person('Einstein');
console.log(Einstein.getName()); // Einstein
Как видно из примера, все работает как положено.
Вообще стоит подметить, при каждом вызове конструктора в памяти создаются новые функции и новые переменные (свойства). Совершенно очевидно, что это неэкономный подход к расходованию памяти, потому что реализация не изменяется от одного экземпляра к другому. Поэтому эффективней добавлять такие методы и свойства к прототипу функции-конструктора.
MyConstructor.prototype.property = true;
MyConstructor.prototype.getProperty = function () {
return this.property;
};
Любой объект имеет свойство constructor, это ссылка на конструктор данного объекта:
var Adam = new Person('Adam');
var Eva = new Person('Eva');
var Cain = new Eva.constructor('Cain'); // здесь мы обращаемся к конструктору Person
Также можно обращаться и к прототипу конструктора:
Cain.constructor.prototype.child = true;
Создание объектов в форме литералов очень удобно, но при этом теряется возможность проверок следующего типа. Выше был создан объект Adam, конструктором которого является Person, значит в коде можно использовать следующую проверку:
Adam instanceof Person // true
Для объектов в форме литералов конструктор является анонимным, то есть так проверить на соответствие типу не удастся. Стоит также подметить. что в случае каскадного наследования объекты также могут подвергаться проверке, например:
var Mammal = function () {
this.name = 'mammal';
this.getName = function () {
return this.name;
};
};
var Dog = function (name) {
this.name = name || 'dog';
};
Dog.prototype = new Mammal;
var Bob = new Dog('Bob');
console.log(Bob instanceof Dog); // true
console.log(Bob instanceof Mammal); // true
То есть проверка проходит не только по своему типу. но и по родительскому. На последок небольшая схемка. Всем успехов в Ваших делах.