Ð ÑовÑеменном JavaScript поÑвилÑÑ Ð½Ð¾Ð²Ñй, «более кÑаÑивÑй» ÑинÑакÑÐ¸Ñ Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов.
ÐÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ class â ÑдобнÑй «ÑинÑакÑиÑеÑкий ÑаÑ
аÑ» Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½ÑÑÑÑкÑоÑа вмеÑÑе Ñ Ð¿ÑоÑоÑипом.
Class
СинÑакÑÐ¸Ñ Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов вÑглÑÐ´Ð¸Ñ Ñак:
class Ðазвание [extends РодиÑелÑ] {
constructor
меÑодÑ
}
ÐапÑимеÑ:
'use strict';
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User("ÐаÑÑ");
user.sayHi(); // ÐаÑÑ
ФÑнкÑÐ¸Ñ constructor запÑÑкаеÑÑÑ Ð¿Ñи Ñоздании new User, оÑÑалÑнÑе меÑÐ¾Ð´Ñ Ð·Ð°Ð¿Ð¸ÑÑваÑÑÑÑ Ð² User.prototype.
ÐÑо обÑÑвление пÑимеÑно аналогиÑно ÑакомÑ:
function User(name) {
this.name = name;
}
User.prototype.sayHi = function() {
alert(this.name);
};
РобоиÑ
ÑлÑÑаÑÑ
new User бÑÐ´ÐµÑ ÑоздаваÑÑ Ð¾Ð±ÑекÑÑ. ÐеÑод sayHi Ñакже в обоиÑ
ÑлÑÑаÑÑ
наÑ
одиÑÑÑ Ð² пÑоÑоÑипе.
Ðо пÑи обÑÑвлении ÑеÑез class еÑÑÑ Ð¸ ÑÑд оÑлиÑий:
UserнелÑÐ·Ñ Ð²ÑзÑваÑÑ Ð±ÐµÐ·new, бÑÐ´ÐµÑ Ð¾Ñибка.- ÐбÑÑвление клаÑÑа Ñ ÑоÑки зÑÐµÐ½Ð¸Ñ Ð¾Ð±Ð»Ð°ÑÑи видимоÑÑи ведÑÑ ÑÐµÐ±Ñ ÐºÐ°Ðº
let. Ð ÑаÑÑноÑÑи, оно видно ÑолÑко в ÑекÑÑем блоке и ÑолÑко в коде, коÑоÑÑй Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð½Ð¸Ð¶Ðµ обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ (Function Declaration видно и до обÑÑвлениÑ).
ÐеÑодÑ, обÑÑвленнÑе внÑÑÑи class, Ñакже имеÑÑ ÑÑд оÑобенноÑÑей:
- ÐеÑод
sayHiÑвлÑеÑÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ меÑодом, Ñо еÑÑÑ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп кsuper. - ÐÑе меÑÐ¾Ð´Ñ ÐºÐ»Ð°ÑÑа ÑабоÑаÑÑ Ð² ÑÑÑогом Ñежиме
use strict, даже еÑли он не Ñказан. - ÐÑе меÑÐ¾Ð´Ñ ÐºÐ»Ð°ÑÑа не пеÑеÑиÑлимÑ. То еÑÑÑ Ð² Ñикле
for..inпо обÑекÑÑ Ð¸Ñ Ð½Ðµ бÑдеÑ.
Class Expression
Также, как и Function Expression, клаÑÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ задаваÑÑ Â«Ð¸Ð½Ð»Ð°Ð¹Ð½Â», в лÑбом вÑÑажении и внÑÑÑи вÑзова ÑÑнкÑии.
ÐÑо назÑваеÑÑÑ Class Expression:
'use strict';
let User = class {
sayHi() { alert('ÐÑивеÑ!'); }
};
new User().sayHi();
РпÑимеÑе вÑÑе Ñ ÐºÐ»Ð°ÑÑа Ð½ÐµÑ Ð¸Ð¼ÐµÐ½Ð¸, ÑÑо один-в-один ÑооÑвеÑÑÑвÑÐµÑ ÑинÑакÑиÑÑ ÑÑнкÑий. Ðо Ð¸Ð¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ даÑÑ. Тогда оно, как и в Named Function Expression, бÑÐ´ÐµÑ Ð´Ð¾ÑÑÑпно ÑолÑко внÑÑÑи клаÑÑа:
'use strict';
let SiteGuest = class User {
sayHi() { alert('ÐÑивеÑ!'); }
};
new SiteGuest().sayHi(); // ÐÑивеÑ
new User(); // оÑибка
РпÑимеÑе вÑÑе Ð¸Ð¼Ñ User бÑÐ´ÐµÑ Ð´Ð¾ÑÑÑпно ÑолÑко внÑÑÑи клаÑÑа и Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ÑполÑзовано, напÑимеÑ, Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²ÑÑ
обÑекÑов данного Ñипа.
Ðаиболее оÑÐµÐ²Ð¸Ð´Ð½Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑÑ Ð¿ÑÐ¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÑÑой возможноÑÑи â Ñоздание вÑпомогаÑелÑного клаÑÑа пÑÑмо пÑи вÑзове ÑÑнкÑии.
ÐапÑимеÑ, ÑÑнкÑÐ¸Ñ createModel в пÑимеÑе ниже ÑоздаÑÑ Ð¾Ð±ÑÐµÐºÑ Ð¿Ð¾ клаÑÑÑ Ð¸ даннÑм, добавлÑÐµÑ ÐµÐ¼Ñ _id и пиÑÐµÑ Ð² «ÑееÑÑÑ» allModels:
'use strict';
let allModels = {};
function createModel(Model, ...args) {
let model = new Model(...args);
model._id = Math.random().toString(36).slice(2);
allModels[model._id] = model;
return model;
}
let user = createModel(class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}, "ÐаÑÑ");
user.sayHi(); // ÐаÑÑ
alert( allModels[user._id].name ); // ÐаÑÑ
ÐеÑÑеÑÑ, ÑеÑÑеÑÑ Ð¸ вÑÑиÑлÑемÑе ÑвойÑÑва
РклаÑÑаÑ
, как и в обÑÑнÑÑ
обÑекÑаÑ
, можно обÑÑвлÑÑÑ Ð³ÐµÑÑеÑÑ Ð¸ ÑеÑÑеÑÑ ÑеÑез get/set, а Ñакже иÑполÑзоваÑÑ [â¦] Ð´Ð»Ñ ÑвойÑÑв Ñ Ð²ÑÑиÑлÑемÑми именами:
'use strict';
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// геÑÑеÑ
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
// ÑеÑÑеÑ
set fullName(newValue) {
[this.firstName, this.lastName] = newValue.split(' ');
}
// вÑÑиÑлÑемое название меÑода
["test".toUpperCase()]() {
alert("PASSED!");
}
};
let user = new User("ÐаÑÑ", "ÐÑпков");
alert( user.fullName ); // ÐаÑÑ ÐÑпков
user.fullName = "Ðван ÐеÑÑов";
alert( user.fullName ); // Ðван ÐеÑÑов
user.TEST(); // PASSED!
ÐÑи ÑÑении fullName бÑÐ´ÐµÑ Ð²Ñзван меÑод get fullName(), пÑи пÑиÑвоении â меÑод set fullName Ñ Ð½Ð¾Ð²Ñм знаÑением.
class не позволÑÐµÑ Ð·Ð°Ð´Ð°Ð²Ð°ÑÑ ÑвойÑÑва-знаÑениÑÐ ÑинÑакÑиÑе клаÑÑов, как Ð¼Ñ Ð²Ð¸Ð´ÐµÐ»Ð¸ вÑÑе, можно ÑоздаваÑÑ Ð¼ÐµÑодÑ. Ðни бÑдÑÑ Ð·Ð°Ð¿Ð¸ÑÐ°Ð½Ñ Ð² пÑоÑоÑип, как напÑÐ¸Ð¼ÐµÑ User.prototype.sayHi.
Ðднако, Ð½ÐµÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑи задаÑÑ Ð² пÑоÑоÑипе обÑÑное знаÑение (не ÑÑнкÑиÑ), Ñакое как User.prototype.key = "value".
ÐонеÑно, никÑо не меÑÐ°ÐµÑ Ð¿Ð¾Ñле обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа в пÑоÑоÑип допиÑаÑÑ Ð¿Ð¾Ð´Ð¾Ð±Ð½Ñе ÑвойÑÑва, однако пÑедполагаеÑÑÑ, ÑÑо в пÑоÑоÑипе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑолÑко меÑодÑ.
ÐÑли ÑвойÑÑво-знаÑение, вÑÑ Ð¶Ðµ, Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾, Ñо можно ÑоздаÑÑ Ð³ÐµÑÑеÑ, коÑоÑÑй бÑÐ´ÐµÑ Ð½Ñжное знаÑение возвÑаÑаÑÑ.
СÑаÑиÑеÑкие ÑвойÑÑва
ÐлаÑÑ, как и ÑÑнкÑиÑ, ÑвлÑеÑÑÑ Ð¾Ð±ÑекÑом. СÑаÑиÑеÑкие ÑвойÑÑва клаÑÑа User â ÑÑо ÑвойÑÑва непоÑÑедÑÑвенно User, Ñо еÑÑÑ Ð´Ð¾ÑÑÑпнÑе из него «ÑеÑез ÑоÑкÑ».
ÐÐ»Ñ Ð¸Ñ
обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¸ÑполÑзÑеÑÑÑ ÐºÐ»ÑÑевое Ñлово static.
ÐапÑимеÑ:
'use strict';
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
static createGuest() {
return new User("ÐоÑÑÑ", "СайÑа");
}
};
let user = User.createGuest();
alert( user.firstName ); // ÐоÑÑÑ
alert( User.createGuest ); // createGuest ... (ÑÑнкÑиÑ)
Ðак пÑавило, они иÑполÑзÑÑÑÑÑ Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑий, не ÑÑебÑÑÑиÑ
налиÑÐ¸Ñ Ð¾Ð±ÑекÑа, напÑÐ¸Ð¼ÐµÑ â Ð´Ð»Ñ ÑабÑиÑнÑÑ
, как в пÑимеÑе вÑÑе, Ñо еÑÑÑ ÐºÐ°Ðº алÑÑеÑнаÑивнÑе ваÑианÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑоÑа. Ðли же, можно добавиÑÑ Ð¼ÐµÑод User.compare, коÑоÑÑй бÑÐ´ÐµÑ ÑÑавниваÑÑ Ð´Ð²ÑÑ
полÑзоваÑелей Ð´Ð»Ñ Ñелей ÑоÑÑиÑовки.
Также ÑÑаÑиÑеÑкими Ñдобно делаÑÑ ÐºÐ¾Ð½ÑÑанÑÑ:
'use strict';
class Menu {
static get elemClass() {
return "menu"
}
}
alert( Menu.elemClass ); // menu
ÐаÑледование
СинÑакÑиÑ:
class Child extends Parent {
...
}
ÐоÑмоÑÑим как ÑÑо вÑглÑÐ´Ð¸Ñ Ð½Ð° пÑакÑике. РпÑимеÑе ниже обÑÑвлено два клаÑÑа: Animal и наÑледÑÑÑий Ð¾Ñ Ð½ÐµÐ³Ð¾ Rabbit:
'use strict';
class Animal {
constructor(name) {
this.name = name;
}
walk() {
alert("I walk: " + this.name);
}
}
class Rabbit extends Animal {
walk() {
super.walk();
alert("...and jump!");
}
}
new Rabbit("ÐаÑÑ").walk();
// I walk: ÐаÑÑ
// and jump!
Ðак видим, в new Rabbit доÑÑÑÐ¿Ð½Ñ ÐºÐ°Ðº Ñвои меÑодÑ, Ñак и (ÑеÑез super) меÑÐ¾Ð´Ñ ÑодиÑелÑ.
ÐÑо поÑомÑ, ÑÑо пÑи наÑледовании ÑеÑез extends ÑоÑмиÑÑеÑÑÑ ÑÑандаÑÑÐ½Ð°Ñ ÑепоÑка пÑоÑоÑипов: меÑÐ¾Ð´Ñ Rabbit наÑ
одÑÑÑÑ Ð² Rabbit.prototype, меÑÐ¾Ð´Ñ Animal â в Animal.prototype, и они ÑвÑÐ·Ð°Ð½Ñ ÑеÑез __proto__:
'use strict';
class Animal { }
class Rabbit extends Animal { }
alert( Rabbit.prototype.__proto__ == Animal.prototype ); // true
Ðак видно из пÑимеÑа вÑÑе, меÑÐ¾Ð´Ñ ÑодиÑÐµÐ»Ñ (walk) можно пеÑеопÑеделиÑÑ Ð² наÑледнике. ÐÑи ÑÑом Ð´Ð»Ñ Ð¾Ð±ÑаÑÐµÐ½Ð¸Ñ Ðº ÑодиÑелÑÑÐºÐ¾Ð¼Ñ Ð¼ÐµÑÐ¾Ð´Ñ Ð¸ÑполÑзÑÑÑ super.walk().
С конÑÑÑÑкÑоÑом â немного оÑÐ¾Ð±Ð°Ñ Ð¸ÑÑоÑиÑ.
ÐонÑÑÑÑкÑÐ¾Ñ constructor ÑодиÑÐµÐ»Ñ Ð½Ð°ÑледÑеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки. То еÑÑÑ, еÑли в поÑомке не Ñказан Ñвой constructor, Ñо иÑполÑзÑеÑÑÑ ÑодиÑелÑÑкий. РпÑимеÑе вÑÑе Rabbit, Ñаким обÑазом, иÑполÑзÑÐµÑ constructor Ð¾Ñ Animal.
ÐÑли же Ñ Ð¿Ð¾Ñомка Ñвой constructor, Ñо, ÑÑÐ¾Ð±Ñ Ð² нÑм вÑзваÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ ÑодиÑÐµÐ»Ñ â иÑполÑзÑеÑÑÑ ÑинÑакÑÐ¸Ñ super() Ñ Ð°ÑгÑменÑами Ð´Ð»Ñ ÑодиÑелÑ.
ÐапÑимеÑ, вÑзовем конÑÑÑÑкÑÐ¾Ñ Animal в Rabbit:
'use strict';
class Animal {
constructor(name) {
this.name = name;
}
walk() {
alert("I walk: " + this.name);
}
}
class Rabbit extends Animal {
constructor() {
// вÑзваÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ Animal Ñ Ð°ÑгÑменÑом "ÐÑолÑ"
super("ÐÑолÑ"); // Ñо же, ÑÑо и Animal.call(this, "ÐÑолÑ")
}
}
new Rabbit().walk(); // I walk: ÐÑолÑ
ÐÐ»Ñ Ñакого вÑзова еÑÑÑ Ð½ÐµÐ±Ð¾Ð»ÑÑие огÑаниÑениÑ:
- ÐÑзваÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ ÑодиÑÐµÐ»Ñ Ð¼Ð¾Ð¶Ð½Ð¾ ÑолÑко изнÑÑÑи конÑÑÑÑкÑоÑа поÑомка. Ð ÑаÑÑноÑÑи,
super()нелÑÐ·Ñ Ð²ÑзваÑÑ Ð¸Ð· пÑоизволÑного меÑода. - РконÑÑÑÑкÑоÑе поÑомка Ð¼Ñ Ð¾Ð±ÑÐ·Ð°Ð½Ñ Ð²ÑзваÑÑ
super()до обÑаÑÐµÐ½Ð¸Ñ Ðºthis. Ðо вÑзоваsuperне ÑÑÑеÑÑвÑеÑthis, Ñак как по ÑпеÑиÑикаÑии в ÑÑом ÑлÑÑае именноsuperиниÑиализиÑÑеÑthis.
ÐÑоÑое огÑаниÑение вÑглÑÐ´Ð¸Ñ Ð½ÐµÑколÑко ÑÑÑанно, поÑÑÐ¾Ð¼Ñ Ð¿ÑоиллÑÑÑÑиÑÑем его пÑимеÑом:
'use strict';
class Animal {
constructor(name) {
this.name = name;
}
}
class Rabbit extends Animal {
constructor() {
alert(this); // оÑибка, this не опÑеделÑн!
// обÑÐ·Ð°Ð½Ñ Ð²ÑзваÑÑ super() до обÑаÑÐµÐ½Ð¸Ñ Ðº this
super();
// а Ð²Ð¾Ñ Ð·Ð´ÐµÑÑ Ñже можно иÑполÑзоваÑÑ this
}
}
new Rabbit();
ÐÑого
- ÐлаÑÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ обÑÑвлÑÑÑ ÐºÐ°Ðº в оÑновном поÑоке кода, Ñак и «инлайн», по аналогии Ñ Function Declaration и Expression.
- РобÑÑвлении клаÑÑов можно иÑполÑзоваÑÑ Ð¼ÐµÑодÑ, геÑÑеÑÑ/ÑеÑÑеÑÑ Ð¸ вÑÑиÑлимÑе Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¼ÐµÑодов.
- ÐÑи наÑледовании вÑзов конÑÑÑÑкÑоÑа ÑодиÑÐµÐ»Ñ Ð¾ÑÑÑеÑÑвлÑеÑÑÑ ÑеÑез
super(...args), вÑзов ÑодиÑелÑÑÐºÐ¸Ñ Ð¼ÐµÑодов â ÑеÑезsuper.method(...args).
ÐонÑепÑÐ¸Ñ ÐºÐ»Ð°ÑÑов, коÑоÑÐ°Ñ Ð¿Ð¾Ñле Ð´Ð¾Ð»Ð³Ð¸Ñ Ð¾Ð±ÑÑждений полÑÑилаÑÑ Ð² ÑÑандаÑÑе ECMAScript, ноÑÐ¸Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ «макÑималÑно минималÑной». То еÑÑÑ, в Ð½ÐµÑ Ð²Ð¾Ñли ÑолÑко Ñе возможноÑÑи, коÑоÑÑе Ñж ÑоÑно Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ñ.
Ð ÑаÑÑноÑÑи, не воÑли «пÑиваÑнÑе» и «заÑиÑÑннÑе» ÑвойÑÑва. То еÑÑÑ, вÑе ÑвойÑÑва и меÑÐ¾Ð´Ñ ÐºÐ»Ð°ÑÑа ÑÐµÑ Ð½Ð¸ÑеÑки доÑÑÑÐ¿Ð½Ñ ÑнаÑÑжи. Ðозможно, они поÑвÑÑÑÑ Ð² бÑдÑÑÐ¸Ñ ÑедакÑиÑÑ ÑÑандаÑÑа.

ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)