آیا Class، Object را تعمیم میدهد؟
همانطور که میدانیم، تمام شیءهای به صورت طبیعی از Object.prototype
ارثبری میکنند و به متدهای «عموnode می» مثل hastOwnProperty
و بقیه آنها دسترسی دارند.
برای مثل:
class Rabbit {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
// است Object.prototype از hasOwnProperty متد
alert( rabbit.hasOwnProperty('name') ); // true
اما اگر ما به طور واضح "class Rabbit extends Object"
را بیان کنیم، سپس نتیجه از یک کلاس ساده "class Rabbit"
متفاوت خواهد بود؟
تفاوت در چیست؟
اینجا مثالی از چنین کدی داریم (این کد کار نمیکند – چرا؟ آن را درست کنید):
class Rabbit extends Object {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // ارور
اول، بیایید ببینیم که چرا کد کار نمیکند.
اگر سعی کنیم که آن را اجرا کنیم دلیل واضح میشود. سازنده کلاس ارثبر باید super()
را فراخوانی کند. در غیر این صورت "this"
«تعریف شده» نخواهد بود.
حل این مشکل:
class Rabbit extends Object {
constructor(name) {
super(); // باید هنگام ارثبری سازنده والد را فراخوانی کنیم
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // true
اما این هنوز تمام ماجرا نیست.
حتی بعد از رفع این مشکل، هنوز هم یک تفاوت اساسی بین "class Rabbit extends Object"
و class Rabbit
وجود دارد.
همانطور که میدانیم، سینتکس “extends” دو پروتوتایپ را تنظیم میکند:
- بین
"prototype"
سازنده تابعها (برای متدها). - بین خود سازنده تابعها (برای متدهای ایستا).
در مورد class Rabbit extends Object
یعنی:
class Rabbit extends Object {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true
پس حالا Rabbit
به دسترسی متدهای ایستای Object
از طریق Rabbit
را فراهم میکند، مثلا اینگونه:
class Rabbit extends Object {}
// را فراخوانی میکنیم Object.getOwnPropertyNames معمولا ما
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
اما اگر ما extends Object
را نداشته باشیم، سپس Rabbit.__proto__
برابر با Object
نخواهد بود.
اینجا یک دمو قرار دارد:
class Rabbit {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // به صورت پیشفرض، مانند هر تابعی
// وجود ندارد Rabbit ارور، چنین تابعی درون
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // ارور
پس در این صورت Rabbit
دسترسی به متدهای ایستای Object
را فراهم نمیکند.
راستی، Function.prototype
دارای متدهای «عمومی» تابع است، مثل call
، bind
و غیره. آنها سرانجام در هر دو مورد در دسترس هستند چون سازنده درونساخت Object
، Object.__proto__ === Function.prototype
را دارد.
اینجا تصویر آن را داریم:
پس، به طور خلاصه، دو تفاوت وجود دارد:
class Rabbit | class Rabbit extends Object |
---|---|
– | باید super() را دورن سازنده فراخوانی کند |
Rabbit.__proto__ === Function.prototype |
Rabbit.__proto__ === Object |