Obeject Data Structure in JavaScript
هر زبان برنامه نویسی از دو ساختار اصلی تشکیل شده است . بخش اول (Data Structure) ساختمان های داده آن و بخش دوم لیست عملیات های آن (Statements) . ممکن است هر قسمت از یک ساختمان داده رفتاری متفاوت در زبان دیگر داشته باشد.
Object or Primitive
در جاوا اسکریپت مفاهیم یا شئ هستند و یا داده اولیه (Object or Primitive value) به این شکل که داده هایی که متد و ویژگی (Methods and Properties) نداشته باشند جزو داده های اولیه هستند و بقیه داده ها که متد و ویژگی دارند شئ هستند. داده های اولیه در جاوا اسکریپت :
- string
- number
- boolean
- null
- undefined
- symbol
- bigint
این ساختمان های داده در جاوا اسکریپت مقادیر آن ها قابل تغییر نیست مثل Array , Object و ما وقتی مقدار 54 را تعریفن می کنیم مقدار نهایی همین است . در صورتی که این مقادیر در const تعریف گردند قابل تغییر نمی باشند.
همه چیز در جاوا اسکریپت شئ است :
Boolean()
Number()
String()
Function()
Object()
Array()
تمامی موارد بالا اگر با کلمه کلیدی new تعریف گردند به صورت شئ عمل خواهند کرد. نوع داده Boolean, Number , String به صورت primitive نیز قابل تعریف هستند. برای تعریف این نوع داده ها به صورت شئ باید از کلمه کلیدی new استفاده کنیم.
اشیا در جاوا اسکریپت بسیار زیاد می باشند و هر کدام یک مبحث باشند (Promise , Error , …) ولی یک سری اشیا اولیه در جاوا اسکریپت داریم. تمام مقادیر جاوا اسکریپت، به جز مقادیر اولیه (Primitive value like number , string , undefined , boolean , null)، اشیا هستند. هر شئ که با کلید new ساخته شود (new String
, new Number
, new Boolean
) در زمانی که با کلمه new صدا زده می شوند شئ هستند و در صورتی که به صورت ساده تعریف شده باشند جزو Primitive value ها هستند.
Date , Math , Regular expression , Functions , Array , Objects همیشه یک شئ هستند و همچنین این مورد را می توان از رفتار آن ها نیز فهمید (به این شکل که یک سری متد و یک سری ویژگی دارند)
برای فهم بهتر اهمیت استفاده از اشیا و مدل سازی آن ها مقاله اشیا در جاواسکریپت را مطالعه فرمایید.
Object
ساختمان داده اشیا در جاوا اسکریپت برای نگهداری به صورت کلید مقدار در برای ساخت موجودیت های پیشرفته تر کاربرد دارد. تقریبا همه اشیا در جاوا اسکریپت از موجودیت Object ساخته شده اند . اشیا در جاوا اسکریپت بسیار نزدیک به ماهیت Associative arrays در زبان پی اچ پی است.
هر متغیر می تواند یک یا چند مقدار بگیرد. اگر قرار بر نگهداری یک collection از داده ها در یک متغیر داشتیم از ساختار Array , Object استفاده می کنیم. برای تعریف کردن اشیا از ساختار کلید : مقدار ("key":"value"
) استفاده می کنیم دقت داشته باشید هم کلید و هم مقدار در میان “” قرار گرفته اند و همچنین بهتر است بین : فاصله اضافی نداشته باشیم این یک Best Practice است.
اشیا نیز در یک متغیر تعریف می شوند تا به آن دسترسی داشته باشیم (در هارددیسک). در جاوا اسکریپت به دو روش زیر می توان شئ را تعریف کرد :
- به صورت عادی با {}
- با استفاده از کلمه کلیدی new Object
- با استفاده از متد Object.create
- به وسیله Object Constructor به طور مثال
new String()
,new Number()
const person = { firstName: "John", lastName: "Doe", age: 50, eyeColor: "blue" }; //-------------------------type 2 const person = {}; person.firstName = "John"; person.lastName = "Doe"; person.age = 50; person.eyeColor = "blue"; //-------------------------type 3 const person = new Object(); person.firstName = "John"; person.lastName = "Doe"; person.age = 50; person.eyeColor = "blue";
نکته مهم Best Practice : بهتر است به عنوان یک عادت خوب اشیا و آرایه ها را در const تعریف کنیم. به این دو ماهیت ساختمان داده های پیشرفته در جاوا اسکریپت می گوییم و const رفتار خاص تری با موجودیت های برگرفته از این ساختمان داده دارد . (اعضای آن قابل ویرایش و حذف هستند ولی کل متغیر قابل ReAssign نیست )
در داخل اشیا ما می توانیم هر یک از ساختمان داده های String , number , null , Nan , Undefined , Function , Array را تعریف کنیم. پس اگر اسم Json Array را شنیدید بدانید که در آن اشیا است که داخل آن آرایه تعریف شده است.
var person = { "name":"John", "age":30, "cars":["Ford", "BMW", "Fiat"] }
برای تعریف یک شئ می توانید از ساختار زیر استفاده کنید( کلیدها در میان ""
قرار بگیرند در صورتی که در کلید ما از کاراکتر – استفاده کنیم.) و اگر به صورت رشته ساده باشند می توان به صورت عادی کلید ها را تعریف کرد.
const person = { name: 'ali', famil: 'alavi', job: 'sfs', "education-1": "elementry", }
در ES6 می توان به صورت زیر هم با این گونه کلید ها برخورد کرد:
const person = { name: 'ali', famil: 'alavi', job: 'sfs', ["education-1"]: "elementry" }
Access , Update , Delete in Object
برای دسترسی به یک المان در یک object هم می توان از روش object استفاده کرد و هم می توان مثل یک Array رفتار کرد هم می توان به صورت ترکیبی از دو روش استفاده کرد.
به طور مثال برای آخرین شئ تعریف شده در بالا person Object :
person.name //"John" person["name"] //"John" person.car[0] //"Ford"
به همان روش که به اعضای یک شی یا آرایه دسترسی داریم می توانیم مقدار آن را بروزرسانی کنیم
person.name="jafar" person["name"]="jafar" person.car[0]="peykan"
برای افزودن یک متغیر به عنوان یک عضو از یک شئ می توان از ساختار زیر استفاده کرد:
var name='ali' var person = { name, famil: 'alavi', job: 'sfs', } person //Object { name: "ali", famil: "alavi", job: "sfs" }
همچنین می توان با همین syntax یک تابع را نیز به یک شئ افزود . به این نوع syntax ها shorthand می گوییم که زیبا تر خوانا تر و سریع تر نوشته می شود . حالت پیش فرض را longhand می گوییم .می توانید مثال های زیادی از shorthand ها در جاوا اسکریپت ببینید.
const person = { name: 'ali', getName(){ return this.name } }
برای تعریف یک عضو به یک شئ به صورت ثابت و بدون تغییر (read-only property) از ساختار Object.defineProperty استفاده کرد.
let person={} Object.defineProperty(person,'id',{value:0922229174,writable:false}) person.id //922229174 person.id = 'hello' person.id //922229174
در ساختار بالا زمانی که property با کلید id را به صورت شخصی تعریف کردیم و مقدار دهی مجدد کردیم مقدار جدید ست نشد.
برای حذف یک عضو از یک شئ لازم است از عبارت delete thisIsObject[key]
یا delete thisIsObject.cow
استفاده کنیم. سه روش مرسوم برای حذف:
//-----------------------------Type1 delete person["name"]; //-----------------------------Type2 delete person.name;
Loop throw an Objects
برای پیمایش میان اشیا ما از statements های جاوا اسکریپت استفاده می کنیم . دو statement معروف برای پیمایش for...in
است .
for (var key in person) { console.log(key + " is equal to " + person.key) }
راه حل دوم استفاده ترکیبی از Object.entries
و for...of
است که در لیست static methods آن را بررسی می کنیم.
const object1 = { a: 'somestring', b: 42 }; for (const [key, value] of Object.entries(object1)) { console.log(`${key}: ${value}`); } // expected output: // "a: somestring" // "b: 42"
راه حل سوم استفاده ترکیبی از Object.entries , Desctructuring می باشد به همراه map :
let person = { name: 'Abolfazl', age: 29, job: 'sfs' } Object.entries(person).map( ([key,value]) => { console.log(key,value) })
نکته مهم این است که به صورت عادی امکان استفاده از for…of برای پیمایش Object وجود ندارد.
Static Methods
تمام اشیا که ما می سازیم گونه ای از شئ Object است.
Method | Description |
Object.assign(target,…source) | همان طور که از نام آن معلوم است متغیر های source را در متغیر target قرار می دهد. کاربرد آن برای کپی یک متغیر در متغیر دیگر یا تقریبا ادغام متغیر هاست.
Object.assign({"name":"ali","famil":"rangin"},{"name":"ahmad","famil":"alavi"}) // { name: "ahmad", famil: "alavi" } Object.assign( {"name":"ali","famil":"rangin"}, {"name":"ahmad","famil":"alavi"}, {"name":"jafar","famil":"haghi"} ) // { name: "jafar", famil: "haghi" } /*---------------------------------------*/ const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object.assign(target, source); let obj1 = { a: 0 , b: { c: 0}}; let obj2 = Object.assign({}, obj1); //{ "a": 0, "b": { "c": 0}} معادل ES6 در این مثال برابر است با syntax var concat = {...{a:1,b:4},...{b:5,c:10}} //Object { a: 1, b: 5, c: 10 } |
Object.create(object) | این برای ساختن یک شئ از روی یک شئ دیگر است .
const person = { isHuman: false, printIntroduction: function() { console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`); } }; const me = Object.create(person); me.name = 'Matthew'; // "name" is a property set on "me", but not on "person" me.isHuman = true; // inherited properties can be overwritten کاربرد دیگر این تابع این است که یک شی به عنوان یک Resource از روی آن می سازیم . const HttpRequest = { #attributes #actions } let requestUpdate = Object.create(HttpRequest) // request update let requestCreate = Object.create(HttpRequest) // request create |
Object.entries(object) | این تابع به صورت یک آرایه هم کلید و هم مقدار را بر می گرداند.
var person = { "name":"Abolfazl", "famil":"sabagh" } console.log(Object.entries(person) Array [ 0: Array [ "name", "Abolfazl" ] 1: Array [ "famil", "sabagh" ] ] |
Object.freeze(object) | این تابع شی را به شکلی فریز می کنند تا قابل ویرایش نباشد.(نه بروزرسانی نه حذف )
const obj = { prop: 42 }; Object.freeze(obj); obj.prop = 33; // Throws an error in strict mode console.log(obj.prop); // expected output: 42 |
Object.keys(object) | لیست کلید ها را برمی گرداند.
const object1 = { a: 'somestring', b: 42, c: false }; console.log(Object.keys(object1)); // expected output: Array ["a", "b", "c"] |
Object.value(object) | لیست مقادیر را بر می گرداند.
const object1 = { a: 'somestring', b: 42, c: false }; console.log(Object.values(object1)); // expected output: Array ["somestring", 42, false] |
Object.defineProperty()
Arguments:
|
برای تعریف یک Property با پارامتر هایی کمی پیشرفته تر قابل تعیین می باشد.
'use strict'; let obj = {}; Object.defineProperty(obj, "x", {value:0, writable:false}); Meta Data :
|
متدهای بالا بخشی از توابعی بود که روی اشیا پیاده سازی برای اهداف خاص پیاده سازی می کردیم. این متد ها برای کار با اشیا در ES5 تعریف شده اند.
Object Inheritance (__proto__)
با استفاده از ویژگی __proto__ می توان یک شئ از دیگری ارث بری کند.
var person = { firstName: 'ali', lastName: 'alavi', getName(){ return `${this.firstName} ${this.lastName}` } } var student = { grade: 15, __proto__: person } student.getName()
Object Resource
این یک روش برای ساخت یک سری اشیا مشابه بدون استفاده از کلاس است . به طور مثال شما می خواهید یک شئ داشته باشید و در عملیات های مختلف (مراحل مختلف یا Event ها) جاواسکریپتی یک سری تغییرات در شئ ایجاد و در نهایت به سرور ارسال کنید.
فرض کنید یک شمارنده ساده داریم که لازم است در هر مرحله یکی بسازیم و به ازای هر Event یک عدد به این شمارنده اضافه کنیم (مثلا فرض کنید یک صلوات شمار به ازای ذکر های مختلف) بدون استفاده از کلاس به روش زیر عمل می کنید.
const counterResource = { "count":0, "init":function(start){ this.count = start }, increase:function(){ this.count++ } }
بلوک کد بالا یک شمارنده است . حال در یک مرحله لازم است یکی از آن بسازیم.
let counterOne = Object.create(CounterResource) counterOne.init(0); counterOne.increase(); counterOne.increase(); console.log(counterOne.count);
می توان به ازای تعداد مشخص از شمارنده ها بسازیم با همین قالب و از آن ها در سیستم استفاده کنیم. یک حافظه مشخص در RAM به ازای هر شمارنده است .
Object Constructor
object ها در جاوا اسکریپت ساختمان داده مناسبی برای ساخت اشیا مورد نظر برای ما هستند . همان طور که می دانیم توابع در جاوا اسکریپت هم شئ هستند و ا گر با کلمه کلیدی new تعریف شوند می توان با آن ها به صورت شئ برخورد کرد. همان شمارنده قبل را با استفاده از Object Constructor تعریف می کنیم.
function Counter(counter){ this.counter = counter this.increase = function(){ this.counter++ } this.getCounter = function(){ return this.counter } } var counter1 = new Counter(0) counter1.increase() counter1.increase() counter1.getCounter() //2
Prototype
تمامی اشیا در جاوا اسکریپت از prototype ارث بری می شوند (Object.prototype , String.prototype, Number.prototype , Date.prototype) حال می توان با استفاده از prototype یک سری متد یا ویژگی به Function Constructor افزود.
Counter.prototype.reset = function(){ this.counter = 0 } var c = new Counter(0) c.increase() c.increase() c.getCounter() //2 c.reset() c.getCounter() //0
در ES5 ما به جای استفاده از Class از ساختار Function Constructor استفاده می کردیم که نوع پیشرفته تری از Object است (در حقیقت یک نوع Object است که constructor دارد). در تعریف Function Constructor بهتر از upper case naming convention استفاده کنید.
دیدگاهتان را بنویسید