Канструктары ў JavaScript таксама адрозніваюцца ад большасці іншых моваў. Любы
выклік функцыі, якому папярэднічае ключавое слова new з'яўляецца канструктарам.
Унутры канструктара (выкліканай функцыі) - значэнне this спасылаецца на
новаствораны аб'ект. Прататыпам новага
аб'екта прызначаецца prototype функцыі, што была выклікана ў якасці канструктара.
У выпадку, калі выкліканая функцыя не вяртае яўнага значэння праз return, будзе
не яўна вернута значэнне this, то бок новы аб'ект.
function Person(name) {
this.name = name;
}
Person.prototype.logName = function() {
console.log(this.name);
};
var sean = new Person();
У гэтым прыкладзе Person выклікаецца ў якасці канструктара, адпаведна prototype
створанага аб'екта будзе прывязаны да Person.prototype.
Вярнуць яўнае значэнне праз return, можна толькі калі гэта значэнне - Object.
function Car() {
return 'ford';
}
new Car(); // новы аб'ект, не 'ford'
function Person() {
this.someValue = 2;
return {
name: 'Charles'
};
}
new Person(); // вяртае аб'ект ({name:'Charles'}), які не ўтрымлівае someValue
Калі ключавое слова new прапушчана, функцыя не верне аб'ект.
function Pirate() {
// пазначыць значэнне ў глабальным аб'екце!
this.hasEyePatch = true;
}
var somePirate = Pirate(); // somePirate == undefined
Гэты прыклад можа спрацаваць у некаторых выпадках, праз тое як працуе
this у JavaScript. Значэннем this тут будзе
глабальны аб'ект.
Каб мець магчымасць прапусціць ключавое слова new, канструктар функцыі мае яўна
вяртаць значэнне.
function Robot() {
var color = 'gray';
return {
getColor: function() {
return color;
}
}
}
new Robot();
Robot();
Абодва выклікі Robot вернуць тое ж самае, новы аб'ект, які мае ўласцівасць
getColor, што з'яўляецца замыканнем.
Таксама варта адзначыць, што выклік new Robot() не ўплывае на прататып
вернутага аб'екта. Хаця прататып будзе прызначаны новастворанаму аб'екту, Robot
ніколі не верне гэты аб'ект.
У прыкладзе вышэй, няма розніцы паміж выклікам функцыі з аператарам new або
без яго.
Часта рэкамендуюць не выкарыстоўваць new бо забыўшыся выкарыстаць яго, можна
стварыць памылку.
Каб стварыць новы аб'ект, лепш выкарыстоўваць фабрыку і стварыць новы аб'ект унутры фабрыкі.
function CarFactory() {
var car = {};
car.owner = 'nobody';
var milesPerGallon = 2;
car.setOwner = function(newOwner) {
this.owner = newOwner;
}
car.getMPG = function() {
return milesPerGallon;
}
return car;
}
Хоць гэты прыклад і спрацуе негледзячы на забытае new, і бясспрэчна выкарыстоўвае
прыватныя пераменныя, ён мае некалькі недахопаў.
- Ён выкарыстоўвае больш памяці, бо функцыі створаных аб'ектаў не захоўваюццца у прататыпе, а ствараюцца на нова для кожнага аб'екта.
- Каб эмуляваць спадкаемства, фабрыка мае скапіраваць метады іншага аб'екта, або пазначыць прататыпам новага аб'екта стары.
- Разрыў ланцужка прататыпаў, проста па прычыне забытага ключавога слова
new, не адпавядае духу мовы JavaScript.
Негледзячы на тое, што прапушчанае new можа выліцца ў памылку, гэта не
прычына адмовіцца ад выкарыстання прататыпаў. У выніку лепш высвятліць якое рашэнне
больш адпавядае патрабаванням праграмы. Асабліва важна выбраць пэўны стыль і
паслядоўна выкарыстоўваць яго.