وراثت اولیه در جاوا اسکریپت چیست؟ با مثال کد توضیح داده شده است
وراثت نمونه اولیه می تواند مانند یک مفهوم پیچیده باشد که در اصطلاح فنی پوشانده شده است. اما نترس! این راهنما آن را با استفاده از مثالهای واضح و قابل ربط که فراتر از توضیحات معمول کتاب درسی است، تجزیه میکند.
ما اصطلاحات گیج کننده را کنار می گذاریم و روی سناریوهای دنیای واقعی تمرکز می کنیم که به راحتی می توانید آن ها را درک کنید.
در پایان این پست، شما یک متخصص وراثت اولیه خواهید بود و متوجه می شوید که در نهایت کار چندان سختی نبود!
فهرست مطالب
نحوه کار با .prototype Object of a Constructor
چگونه نمونه اولیه یک سازنده را تغییر دهیم
معرفی مفهوم
تصور کنید که من یک پدر و مادر هستم و یک فرزند و یک نوه دارم. اگر بخواهید شجره نامه من را در نمودار نشان دهید، باید به شکل زیر باشد:
می بینید که grandparent
در بالای این شجره خانواده قرار دارند، در حالی که parent
از نوادگان مستقیم grandparent
هستند و child
از نوادگان parent
هستند.
اگر سعی کنید راه خود را به عقب برگردید، خواهید دید که grandchild
فرزند parent
است و والد خودش child
grandparent
است.
اشیاء جاوا اسکریپت چیست؟
ممکن است زمانی با این جمله برخورد کرده باشید: "در جاوا اسکریپت، تقریباً همه چیز یک Object است".
توجه کنید که چگونه Object
را املا کردم؟ هنگامی که من از Object و Object در سراسر این مقاله استفاده می کنم، معنی آنها متفاوت خواهد بود.
Object سازنده ای است که برای ایجاد اشیا استفاده می شود. یعنی: یکی والد/جد و دیگری فرزند.
با استفاده از تصویر شکل 1.0 بالا، بیایید سعی کنیم نحوه عملکرد شجره نامه در جاوا اسکریپت را نشان دهیم.
Object
پدربزرگ و مادربزرگ است.
سازندگانی مانند Array
، String
، Number
، Function
، و Boolean
همگی از نوادگان Object
هستند.
همه آنها فرزندانی از انواع مختلف تولید می کنند: array
، string
، number
، function
و Boolean
. با این حال، اگر منشأ آنها را دنبال کنید، همه آنها Objects
هستند.
پس اگر از شما سوال می شود که چرا همه چیز (به جز null
و undefined
) به عنوان شی در جاوا اسکریپت در نظر گرفته می شود، به این دلیل است که همه آنها از نوادگان سازنده Object
هستند.
سازنده های فهرست شده در تصویر بالا مسئول انواع مختلف داده هایی هستند که در جاوا اسکریپت استفاده می کنید. یعنی از آنها در پشت صحنه برای ایجاد انواع داده های آشنا استفاده می شود (و همچنین می توانید از آنها برای ایجاد مقادیر مختلف به طور صریح استفاده کنید).
بیایید چند قطعه کد را امتحان کنیم.
نحوه ایجاد یک شی
// Using the regular object syntax const newObj = {} // Using the object constructor const newObjWithConstructor = new Object()
نحوه ایجاد یک آرایه
// Using the regular array syntax const newArr = [] // Using the array constructor const newArrWithConstructor = new Array()
نحوه ایجاد یک عدد
// Using the regular syntax const num = 3 // Using the number constructor const numWithConstructor = new Number(3)
نحوه ایجاد یک تابع
// Using regular function syntax function logArg (arg) { console.log(arg) } // Using the Function constructor const logArgWithConstructor = new Function('arg1', 'console.log(arg1)')
چگونه یک Boolean ایجاد کنیم
// Using the regular boolean syntax const isValid = true // Using the Boolean constructor const isValidWithConstructor = new Boolean(true)
می بینید که از نمونه نمونه های بالا، می توان به طور صریح مقادیر را با استفاده از سازنده مناسب ایجاد کرد، یا فقط با استفاده از نحو ساده و به جاوا اسکریپت اجازه داد تا مقدار را با نوع مناسب برای ما ایجاد کند.
توجه : ذکر این نکته مهم است که هر روش ایجاد مقادیر موارد استفاده و عوارض جانبی خاص خود را دارد، اما در این مقاله به آن نخواهیم پرداخت.
سازندگان این مقادیر مختلف چیزی به نام نمونه اولیه دارند.
نمونه اولیه شی چیست؟
در جاوا اسکریپت چیزی به نام prototype
وجود دارد. نزدیکترین مفهوم به این DNA انسان است.
درست مانند DNA که به عنوان نقشههایی عمل میکند که آپشن های ی را تعریف میکند که از طریق نسلهای شجرهنامه انسانی منتقل میشوند، prototypes
در جاوا اسکریپت برای تعریف ویژگیها و روشهایی استفاده میشوند که توسط اشیاء در درخت شی جاوا اسکریپت به ارث برده میشوند.
اجازه دهید شکل 1 و شکل 2 را با هم ترکیب کنیم و اکنون آن را برای تطبیق با مفهوم DNA و نمونه اولیه به روز کنیم.
در جاوا اسکریپت، همه سازنده ها یک نمونه اولیه دارند . نمونه اولیه یک سازنده فرهنگ لغت همه چیزهایی است که مقادیر ایجاد شده با سازنده باید به ارث بروند.
خط بالا ☝️ را دوباره بخوانید و وقتی مشخص شد ادامه دهید.
سازنده را مانند یک پدر و مادر و نمونه اولیه را مانند DNA در نظر بگیرید. هنگامی که سازنده (والد) یک فرزند (ارزش) ایجاد می کند (به دنیا می آورد)، فرزندان از DNA (نمونه اولیه) والد سازنده خود به ارث می برند.
بیایید نمودار دیگری را در نظر بگیریم:
از شکل 4 ، می بینید که یک کودک مستقیماً از والدین خود و والدین آنها ویژگی هایی را از پدربزرگ و مادربزرگ به ارث می برند. در این زنجیره ارث، فرزند در واقع هم از پدربزرگ و هم از پدربزرگ و مادربزرگ ارث می برد.
در واقع، آپشن های کودک به شدت تحت تأثیر ترکیب DNA هر اجداد قبل از خودش است.
به این صورت است که وراثت نمونه اولیه در جاوا اسکریپت کار می کند.
ویژگی های نمونه اولیه سازنده توسط فرزندان ایجاد شده توسط آن سازنده به ارث می رسد. این در زنجیره ادامه دارد. شما می توانید در مورد آن به این صورت استدلال کنید:
هر نسلی که در زنجیره ارث وجود دارد، هر چیزی را که در نمونه اولیه اجدادش موجود است به ارث می برد.
از نمودار بالا، می بینید که تمام نمونه های اولیه از نمونه اولیه Object به ارث می برند. پس ، هر مقدار ایجاد شده با سازنده Array (به عنوان مثال)، از نمونه اولیه Array و همچنین نمونه اولیه Object به ارث می رسد.
این به این دلیل است که نمونه اولیه Array از نمونه اولیه Object به ارث می برد.
عبارت Array prototype به صورت Array.prototype
در جاوا اسکریپت نوشته می شود، در حالی که نمونه اولیه Object Object.prototype
است.
نکته : توجه به این نکته مهم است که مفهوم DNA پیچیده است، پس اگر طولانی شود، به سرعت متوجه میشویم که تفاوتها و تفاوتهایی بین نحوه کار DNA و نمونههای اولیه وجود دارد، اما در سطح بالا، آنها بسیار شبیه هستند.
پس ، درک وراثت در شجره نامه انسانی به ما درک قوی از وراثت نمونه اولیه در جاوا اسکریپت می دهد.
اگر با ویدیوها بهتر یاد می گیرید، قبل از ادامه، این را تماشا کنید .
نحوه کار با .prototype
سازنده
برای مشاهده محتوای نمونه اولیه سازنده، به سادگی theConstructorName.prototype
را می نویسیم. مثال دشمن: Array.prototype
، Object.prototype
، String.prototype
و غیره.
تا به حال تصور کرده اید که چگونه می توان نوشت [2, 8, 10]. map (...)
؟ این به این دلیل است که در نمونه اولیه سازنده Array، کلیدی به نام map
وجود دارد. پس حتی اگر شما map
ویژگی را توسط خودتان ایجاد نکردید، با مقدار آرایه به ارث برده شد زیرا این مقدار توسط سازنده Array
در داخل ایجاد شده است.
جمله بالا را اینگونه بخوانید: آیا تا به حال فکر کرده اید که چرا گروه خونی خاص خود را دارید؟ این به این دلیل است که شما گروه خونی خود را از ژن هایی که از والدین خود به ارث برده اید دریافت می کنید!
پس دفعه بعد که از ویژگی ها و روش هایی مانند .length
، .map
، .reduce
، .valueOf
، .find
، .hasOwnProperty
روی یک مقدار استفاده کردید، فقط به یاد داشته باشید که همه آنها از نمونه اولیه سازنده یا برخی از نمونه های اولیه از نمونه اولیه به ارث برده شده اند. زنجیر (نسب).
شما می توانید نمونه اولیه سازنده را به عنوان نمونه اولیه موجودیت مورد استفاده برای ساخت/ایجاد/ساخت یک مقدار ببینید.
باید بدانید که .prototype
هر سازنده یک شی است. سازنده خود یک تابع است، اما نمونه اولیه آن یک شی است.
console.log(typeof Array) // function console.log(typeof Array.prototype) // object
نکته : یک استثنا در این مورد، نمونه اولیه سازنده Function است. این یک شی تابع است، اما هنوز دارای آپشن های ی است که به آن متصل شدهاند و میتوان به آن ویژگیها دسترسی پیدا کرد، همانطور که با اشیاء معمولی انجام میدهیم (با استفاده از نماد .
).
اگر به خاطر دارید، میتوانیم با استفاده از نقطه، آپشن های جدیدی را به اشیاء اضافه کرده و مقادیر آپشن های موجود را بازیابی کنیم .
نشانه گذاری. به عنوان مثال: objectName.propertyName
const user = { name: "asoluka_tee", stack: ["Python", "JavaScript", "Node.js", "React", "MongoDB"], twitter_url: "https://twitter.com/asoluka_tee" } // Using the syntax objectName.propertyName, to access the name key we'll write; user.name const userName = user.name; console.log(userName) // asoluka_tee // To add a new property to the object we'd write; user.eyeColor = "black" // If we log the user object to the console now, we should see eyeColor as part of the object properties with the value of 'black'
آیا تا به حال در مورد جهش DNA شنیده اید؟ این ایده تغییر DNA افراد است. در جاوا اسکریپت این کار با نمونه های اولیه امکان پذیر است.
درست همانطور که جهش DNA یک چیز بسیار خطرناک برای آزمایش است و نتیجه ممکن است نامشخص باشد یا عوارض جانبی نامطلوب ایجاد کند، تغییر نمونه اولیه سازنده ایده خوبی نیست مگر اینکه بدانید چه کاری انجام می دهید.
چگونه نمونه اولیه یک سازنده را تغییر دهیم
در جاوا اسکریپت، میتوان شی نمونه اولیه سازنده را به همان روشی که با یک شی جاوا اسکریپت معمولی میتوان تغییر داد (همانطور که در بالا نشان داده شده است).
این بار، ما فقط باید این نحو را دنبال کنیم constructorName.prototype.newPropertyName = value
. به عنوان مثال، اگر می خواهید یک ویژگی جدید به نام currentDate
را به شی نمونه اولیه سازنده Array اضافه کنید، باید بنویسید:
//constructorName.prototype.newPropertyName Array.prototype.currentDate = new Date().toDateString();
از این به بعد، در کد شما، چون currentDate
اکنون در نمونه اولیه سازنده Array
(Array.prototype)
وجود دارد، هر آرایه ای که در برنامه ما ایجاد می شود می تواند به این شکل به آن دسترسی داشته باشد: [1, 2, 3].currentDate
و نتیجه خواهد شد. تاریخ امروز باشد
اگر می خواهید هر شی در برنامه جاوا اسکریپت شما به currentDate
دسترسی داشته باشد، باید آن را به نمونه اولیه شی سازنده Object
(Object.prototype)
اضافه کنید:
//constructorName.prototype.newPropertyName Object.prototype.currentDate = new Date().toDateString(); const newArr = [1, 2, 3] const newObj = {} const newBool = true // NB: The date shown is the date of writing this article console.log(newArr.currentDate) // 'Fri May 10 2024' console.log(newObj.currentDate) // 'Fri May 10 2024' console.log(newBool.currentDate) // 'Fri May 10 2024'
این امکان پذیر است زیرا شی نمونه اولیه همه سازنده ها از شی نمونه اولیه سازنده Object
به ارث می برند.
بیایید نسخه خود را از دو روش آرایه محبوب بنویسیم و از آنها درست مانند روش اصلی استفاده کنیم.
Array.prototype.reduce : ما مال خود را .reduceV2
می نامیم
// Add our new function to the prototype object of the Array constructor Array.prototype.reduceV2 = function (reducer, initialValue) { let accum = initialValue; for (let i = 0; i < this.length; i++) { accum = reducer(accum, this[i]); } return accum; }; // Create an array of scores let scores = [10, 20, 30, 40, 50]; // Use our own version of Array.prototype.reduce to sum the values of the array const result = scores.reduceV2(function reducer(accum, curr) { return accum + curr; }, 0); // Log the result to the console console.log(result);
تمرکز در اینجا توضیح کل نحو نیست، بلکه به شما نشان می دهد که با استفاده از زنجیره نمونه اولیه، می توانید متدهای خود را ایجاد کنید و از آنها درست مانند مواردی که جاوا اسکریپت ارائه می دهد استفاده کنید.
توجه داشته باشید که میتوانید .reduceV2
ما را با .reduce
اصلی جایگزین کنید و همچنان کار میکند (در اینجا موارد لبه تحلیل نمیشوند).
2. Array.prototype.map : ما مال خود را .mapV2
می نامیم
// Add mapV2 method to the prototype object of the Array constructor Array.prototype.mapV2 = function (func) { let newArray = []; this.forEach((item, index) => newArray.push(func(item, index))); return newArray; }; // Create an array of scores const scores = [1, 2, 3, 4, 5]; // Use our mapV2 method to increment every item of the scores array by 2 const scoresTimesTwo = scores.mapV2(function (curr, index) { return curr * 2; }) // Log the value of scoresTimesTwo to the console. console.log(scoresTimesTwo)
توجه : ذکر این نکته مهم است که این به هیچ وجه اجرای کامل نسخه های اصلی روش map
جاوا اسکریپت نیست. این فقط تلاشی است برای نشان دادن آنچه که با شی نمونه اولیه سازنده امکان پذیر است.
قبل از اینکه این درس را جمع بندی کنیم، یک چیز دیگر را باید ذکر کنم. این ویژگی __proto__
هر شی است.
دارایی __proto__
__proto__
تنظیم کننده و گیرنده برای [[نمونه اولیه]] ویژگی یک شی است. این بدان معناست که برای تنظیم یا دریافت نمونه اولیه یک شی (مثلاً شیئی که شی دیگری از آن ارث می برد) استفاده می شود.
const user = {} const scores = [] user.prototype // undefined scores.prototype // undefined
در قطعه بالا، سعی کردیم به طور مستقیم از مقادیر به شی نمونه اولیه دسترسی پیدا کنیم. این در جاوا اسکریپت امکان پذیر نیست.
این منطقی است زیرا فقط سازنده ها دارای ویژگی prototype
هستند.
درست مانند جهش DNA خطرناک است، اگر به طور کامل نمی دانید چه کاری انجام می دهید، ممکن است با شی نمونه اولیه آشفته شود.
در شرایط عادی، یک کودک نباید سعی کند DNA جد خود را تغییر دهد یا حتی تعیین کند که صفات را از چه کسی به ارث ببرد.
با این حال، زبان جاوا اسکریپت راهی را برای ما فراهم می کند تا به شی نمونه اولیه از مقادیری که سازنده نیستند با استفاده از ویژگی __proto__
دسترسی پیدا کنیم.
این روش منسوخ شده است و نباید برای پروژه های جدید استفاده شود. من به __proto__
اشاره می کنم زیرا می توانید برای کار در پایگاه کدی که هنوز از آن استفاده می کند، استخدام شوید.
__proto__
به یک مقدار اجازه می دهد تا مستقیماً به شی نمونه اولیه سازنده خود دسترسی پیدا کند. پس اگر به هر دلیلی میخواهید ببینید چه چیزی در زنجیره نمونه اولیه اجداد یک مقدار موجود است، میتوان از ویژگی __proto__
برای آن استفاده کرد.
همچنین می توانید از __proto__
برای تعیین اینکه یک مقدار باید از کدام شی به ارث ببرد استفاده کنید.
به عنوان مثال، ما یک شی به نام human
داریم، و میخواهیم شی دیگری به نام parent
از انسان به ارث ببرد، این کار را میتوان با ویژگی __proto__
والد مانند این انجام داد.
// Create a human object const human = { walk: function () { console.log('sleeping') }, talk: function () { console.log('talking') }, sleep: function () { console.log('sleeping') } } // Create a parent object and configure it to inherit from human. const parent = { __proto__: human } // Use a method from the ancestor of parent parent.sleep() // sleeping
توجه داشته باشید که چگونه میتوانیم روش sleep
را روی parent
صدا کنیم زیرا parent
اکنون از human
ارث میبرند.
روش های توصیه شده مدرن تری برای استفاده در هنگام تعامل با شی نمونه اولیه مانند Object.getPrototypeOf
و Object.setPrototypeOf
وجود دارد.
const user = {} const scores = [] // Get the prototype of the user object console.log(Object.getPrototypeOf(user)) // Change the prototype of the scores array. This is like switching ancestry and should be done with great care. console.log(Object.setPrototypeOf(scores, {})) // Check the prototype of scores now console.log(Object.getPrototypeOf(scores)) // {}
این روش ها باید با دقت زیاد مورد استفاده قرار گیرند. در واقع، شما باید در اسناد MDN JS اطلاعات بیشتری در مورد آنها بخوانید تا اطلاعات بیشتری در مورد مزایا و معایب آنها به دست آورید.
اگر تا این مرحله خوانده باشید، اکنون اصول اولیه Array.prototype
را میدانید و از این به بعد، درک هر مفهوم دیگری که بر روی آن در جاوا اسکریپت ساخته شده است آسانتر خواهد بود.
بیایید آنچه را که تا کنون آموخته اید خلاصه کنیم.
خلاصه
ما سازنده های مختلفی در جاوا اسکریپت داریم: Array
، Boolean
، Function
، Number
، String
و Object
.
Object والد تمام سازنده های دیگر است.
هر سازنده یک شی .prototype
دارد و این شی حاوی ویژگی ها و روش هایی است که می توان با مقادیر ایجاد شده با استفاده از سازنده به آنها دسترسی داشت. برای مثال، مقداری که با استفاده از سازنده Array
ایجاد میشود، به تمام ویژگیها و متدهای موجود در شی Array.prototype
دسترسی خواهد داشت و این وراثت تا آخر بالا میرود.
یعنی مقداری که با استفاده از سازنده Array
ایجاد میشود (چه به صورت ضمنی یا صریح)، نه تنها به ویژگیها و متدهای موجود در شی Array.prototype
، بلکه به ویژگیها و متدهای موجود در شی Object.prototype
نیز دسترسی خواهد داشت.
این به دلیل مفهوم وراثت نمونه اولیه است. Object
والد Array
است و هر فرزند تولید شده توسط Array
به صفات Array
و Object
دسترسی خواهد داشت.
این چیزی است که زمانی اتفاق می افتد که شما سعی می کنید یک ویژگی را از مقداری بدست آورید که به صراحت روی مقدار اعلام نشده است. قطعه کد زیر را ببینید:
const user = {} // trying to retireve .valueOf property from the user object console.log(user.valueOf)
بدیهی است که شی user
هیچ خاصیت .valueOf
ندارد، پس زنجیره اولیه خود را برای هر نمونه اولیه ای که دارای آن ویژگی باشد جستجو می کند و اگر یافت شد، مقدار برگردانده می شود. در غیر این صورت، ما undefined
می شویم.
همچنین یاد گرفتیم که میتوانیم نمونه اولیه هر سازنده را برای گفت ن قابلیت تغییر دهیم و این باید با احتیاط انجام شود.
در نهایت، یاد گرفتیم که چگونه __proto__
، getPrototypeOf
و setPrototypeOf
می توانند برای بازیابی و تنظیم نمونه اولیه یک مقدار استفاده شوند.
این چگونه مفید است؟
تصور کنید که می خواهید متدی ایجاد کنید که یک شی جدید را بر اساس یک آرایه ایجاد می کند و وقتی روی آرایه فراخوانی می شود آن را برمی گرداند.
این یکی برای شماست که خودتان امتحان کنید.
// Array.prototype.toObject const names = ['Austin', 'Tola', 'Joe', 'Victor']; // Write your implementation of toObject here. console.log(names.toObject()) // {0: 'Austin', 1: 'Tola', 2: 'Joe', 3: 'Victor'}
هورای!!! من می دانم که شما در حال حاضر مانند یک نینجا جاوا اسکریپت احساس می کنید.
اگر با ویدیوها بهتر یاد می گیرید، در کانال یوتیوب من مشترک شوید و به زودی ویدیوهای سخنرانی را منتشر خواهم کرد.
با تشکر برای خواندن! کد نویسی مبارک!
ارسال نظر