## Канструктары Канструктары ў JavaScript таксама адрозніваюцца ад большасці іншых моваў. Любы выклік функцыі, якому папярэднічае ключавое слова `new` з'яўляецца канструктарам. Унутры канструктара (выкліканай функцыі) - значэнне `this` спасылаецца на новаствораны аб'ект. [Прататыпам](#object.prototype) **новага** аб'екта прызначаецца `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`](#function.this) у JavaScript. Значэннем `this` тут будзе *глабальны аб'ект*. ### Фабрыкі Каб мець магчымасць прапусціць ключавое слова `new`, канструктар функцыі мае яўна вяртаць значэнне. function Robot() { var color = 'gray'; return { getColor: function() { return color; } } } new Robot(); Robot(); Абодва выклікі `Robot` вернуць тое ж самае, новы аб'ект, які мае ўласцівасць `getColor`, што з'яўляецца [замыканнем](#function.closures). Таксама варта адзначыць, што выклік `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`, і бясспрэчна выкарыстоўвае [прыватныя пераменныя](#function.closures), ён мае некалькі недахопаў. 1. Ён выкарыстоўвае больш памяці, бо функцыі створаных аб'ектаў **не** захоўваюццца у прататыпе, а ствараюцца на нова для кожнага аб'екта. 2. Каб эмуляваць спадкаемства, фабрыка мае скапіраваць метады іншага аб'екта, або пазначыць прататыпам новага аб'екта стары. 3. Разрыў ланцужка прататыпаў, проста па прычыне забытага ключавога слова `new`, не адпавядае духу мовы JavaScript. ### У заключэнне Негледзячы на тое, што прапушчанае `new` можа выліцца ў памылку, гэта **не** прычына адмовіцца ад выкарыстання прататыпаў. У выніку лепш высвятліць якое рашэнне больш адпавядае патрабаванням праграмы. Асабліва важна выбраць пэўны стыль і **паслядоўна** выкарыстоўваць яго.