تعداد بازدید: 317

Object Prototype

ویژگی ارث بری یا inheritance یکی از مفاهیم شئ گرایی در زبان های برنامه نویسی مبتنی بر اشیا می باشد. این قابلیت در Object Literal , Constructor , Class در کاربرد های متفاوت قابل استفاده می باشد. Prototype مکانیزمی است که اشیا می توانند به وسیله آن ویژگی های خود را از شئ دیگر به ارث ببرند (توجه داشته باشید در این جا شئ مطرح است و نه class).

در رابطه با Prototype دو موضوع مطرح است :

  • Prototype Chain : زنجیره ارث بری . همان طور که انسان ها از نسل های قبل خود به ترتیب ارث بری می کنند (فرزند > پدر > پدر بزرگ > پدر جد …) اشیا نیز این ارث بری را دارند تا به انتهای کار یعنی null برسند.
  • Set Prototype : تعیین والد برای یک شئ . در حقیقت تعیین کنیم که این شئ از کدام شئ دیگر ویژگی ها و متد های خود را دریافت کند.

Prototype Chain

در حقیقت یک شئ در جاوا اسکریپت زمانی که یک متد یا یک ویژگی از آن فراخوانده می شود از Prototype آن این فراخوانی انجام می شود . این Prototype را در حقیقت می توانیم همان this صدا بزنیم.

هر شئ در جاوا اسکریپت از والد خود ویژگی ها و متد هایی را ارث بری می کند . به این ترتیب می توان گفت که اشیا تولید شده در مفسر جاوا اسکریپت حداقل یک والد را دارند که یک سری متد را از آن به ارث می برند. به این شئ پیش فرض والد Object Prototype گفته می شود. Property/Methods های پیش فرض آن که در همه اشیا وجود دارد (مگر این که بازنویسی در شئ جاری گردد) از قرار زیر است:

__defineGetter__
__defineSetter__
__lookupGetter__
__lookupSetter__
__proto__
city
constructor
greet
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toLocaleString
toString
valueOf

این ویژگی ها همگی از Object Prototype برمی گردد که والد این مقدار است . اگر متد static با نام Object.getPrototypeOf را فراخوانی کنید می توانید Prototype شئ جاری خود را بدست بیاورید.

let mashhad = {
  name: 'Mashhad',
}
console.log(mashhad.__proto__)
console.log(Object.getPrototypeOf(mashhad))

هر شئ در جاوا اسکریپت یک ویژگی به نام __proto__ دارد که آن به یک Prototype دیگر اشاره می کند و خود Prototype یک شئ است و این شئ هم به طبع یک ویژگی دارد که در آن Prototype والد را درخود جای داده است .

این زنجیره ارث بری به این شکل است که زمانی که شما یک متد از یک شئ را فراخوانی می کنید مفسر این درخواست را در همان Prototype شئ جاری جستجو می کند . پس از آن اگر در شئ جاری یافت نشد در Prototype والد آن جستجو می کند . این زنجیره تا جایی ادامه پیدا می کند که Prototype برابر با null باشد و متد undefined بر می گرداند. پس در حقیقت می توان گفت که زمانی که ما یک متد را از یک شئ فراخوانی می کنیم عملا آن را در Prototype جاری آن جستجو می کنیم و این موضوع که در زمان تعریف متد های Dynamic یک شئ ما به صورت زیر عمل می کنیم از همین فکت نشات می گیرد. به طور مثال برای تعریف متد های Dynamic شئ Promise :

  • Promise.prototype.catch()
  • Promise.prototype.then()
  • Promise.prototype.finally()

Prototype-chain

اشیا پیش فرض در جاوا اسکریپت هم دقیقا همین زنجیره ارث بری را دارند . در مثال زیر ما یک تابع نوشتیم که این زنجیره را پیمایش می کند و اشیا والد را برای ما نمایش می دهد.

function prototypeChain(object) {
  do {
    object = Object.getPrototypeOf(object)
    console.log(object)
  } while (object)
}

let date = new Date
let set = new Set
let map = new Map
console.log('=============== Date ==================')
 prototypeChain(date)

 console.log('=============== Map ===================')
 prototypeChain(map)

 console.log('=============== Set ===================')
 prototypeChain(set)

Shadowing Property (overwrite)

زمانی که ما یک متد از یک شئ مثلا Date را فراخوانی می کنیم به این شکل است که این متد به صورت این متد در Prototype همان شئ جستجو می گردد و اگر یافت شد در همان اجرا می گردد. در صورتی که یافت نشده باشد در __poroto__ آن که Prototype والد آن است جستجو می گردد و به این ترتیب این زنجیره تا یافت شدن متد ادامه پیدا می کند. پس اگر ما یک متد از Prototype والد را بازنویسی کنیم از همان شئ این متد بازنویسی شده در دسترس است.

let d = new Date

console.log('Default getFullYear-------------------')
console.log(d.getFullYear())

console.log('Shadowing getFullYear-----------------')
d.getFullYear = function() {
  return '2019'
}
console.log(d.getFullYear())

Setting a prototype

زمانی که ما یک شئ را از روی یک شئ دیگر می سازیم عملا Prototype آن را به شئ مورد نظر لینک می کنیم. به این ترتیب می توان گفت که Prototype ما عملیات Set Prototype را انجام داده ایم .

روش های مختلفی برای Set Prototype وجود دارد . معمولا دو حالت کلی داریم که یکی ساختن یک شئ از روی یک شئ دیگر است و دیگری ست کردن یک شئ روی یک تابع یا همان constructor می باشد. این دو حالت را با دو متد static زیر بررسی می کنیم.

  • Object.create
  • Object.assign
let Person = {
  name: '',
  setName(name) {
    this.name = name
  },
  getName(){
    return this.name
  }
}

let Professor = Object.create(Person)
Professor.setName('Dennise Ritchie')
Professor.teach = 'Computer sience'

let Student = Object.create(Person)
Student.setName('Abolfazl Sabagh')
Student.grade = 20

console.log('Person,Professor,Student-------------')
console.log(Person,Professor,Student)

روش بالا یکی از پرکاربرد ترین روش ها برای ساخت اشیا از روی نسخه ای دیگر یا همان قالب شئ دیگر است .

اشیا Constructor یک ویژگی خوب دارند که می توانند ویژگی های داخلی خود را در زمان ساخت مقدار دهی کنند. به طور مثال می توان برای شئ Person ویژگی name را تعیین کرد. همچنین می توان شئ درون یک تابع constructor را تعیین کرد که این دقیقات همان Prototype آن است .این کار به دو روش قابل تعیین است. (دقت داشته باشید که این Prototype دقیقا همان مقدار this در جریان این تابع است .)

نکته مهم : Arrow Function ها به دلیل نداشتن this تعریف شده در یک تابع از این موضوع مستثنی هستند.

let PersonPrototype = {
  setName(name){
    this.name = name
  },
  getName(){
    return this.name
  }
}

function Person(name){
  this.name = name
}

Object.assign(Person.prototype,PersonPrototype)

let ali = new Person('Ali')
console.log(ali.getName())

همچنین به وسیله Indirect Invoked (call,apply,bind) می توان یک شی را در بدنه یک تابع جریان داد یا عملا همان set Prototype را انجام داد.

Default Object Prototype

هسته اصلی یک شئ Prototype آن است و می توان گفت که هر شئ از یک کلاس که ساخته می شود Prototype دقیقا همان ویژگی ها و متد های شئ برگرفته از این کلاس است. برای همین زمانی که ما یک متد از یک شئ را می خواهیم تعریف کنید به این شکل عمل می کنیم (به طور مثال برای String) String.prototype.toUppercase

پیرو توضیحات بالا حال اگر قرار است یک شئ خالی ایجاد کنیم می توانیم به شکل زیر عمل کنیم :

let a = Object.create(Object.prototype)

برای این که بتوانیم یک متد جدید برای یک شئ پیش فرض از ساختمان داده های جا وا اسکریپت مثل String , Number , Array و … تعیین کنیم می توانیم مطابق با روال زیر عمل کنیم:

/* convert time string to seconds */
String.prototype.toSecond = function(){
  let arr = this.split(':')
  const [hour,minute,second] = arr
  return parseInt(hour * 3600)  + parseInt(minute * 60) + parseInt(second)
}

در مثال بالا ما اگر یک ساعت را که در یک رشته با فرمت h:m:s قرار گرفته است متد toSecond را برای آن اجرا کنیم تعداد ثانیه را بر می گرداند.

'1:12:33'.toSecond() /*4353*/

 

مطالب مشابه

HTML Element Node

هر سند html از ساختار های مختلفی تشکیل شده است. این ساختار به صورت درختی است و هر قسمت از این ساختار یک موجودیت خاص می...

Math and Arithmetic logic in JavaScript

اعداد در برنامه نویسی کاربردهای بسیار زیادی دارند. مهم ترین شناسه یک موجودیت یک عدد است که به آن Identifier می گوییم که...

webpack javascript module bundler

Webpack Module Bundler

وب پک یک ابزار توسعه (Development Tool) از دسته Module Bundler ها است. وب پک امکان تجمیع و پردازش کردن Module های جاوا...

اشتراک گذاری :

مدیر وب سایت گنوتک . برنامه نویسی رو با زبان C در هفده سالگی شروع کردم . در حال حاضر به برنامه نویسی php برپایه معماری MVC , HMVC و همچنین سیستم مدیریت محتوای WordPress و فریم ورک محبوب لاراول علاقه مند هستم و دوست دارم اطلاعاتم رو با شما به اشتراک بگذارم.

۰ دیدگاه برای Object Prototype

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *