آموزش جاوا اسکریپت – جلسه ۸ – انواع داده [DataTypes]
![آموزش جاوا اسکریپت – جلسه 8 – انواع داده [DataTypes]](https://rahkarino.ir/wp-content/uploads/2020/06/js-part8-datatypes-1.jpg)
در بخش هفتم از آموزش جامع جاوا اسکریپت، تمام مباحث مربوط به آبجکت یا شیء را در زبان جاوا اسکریپت آموزش دادیم. در این مقاله قصد داریم درباره انواع داده در javascript یا DataTypes صحبت کنیم.
متدهای مربوط به انواع دادهای primitive:
جاوا اسکریپت امکان کار کردن با انواع متغیرهای شی (object) و اولیه (primitive) را به ما می دهد. این انواع داده ها، متدهای خودشان را نیز دارند. برای ادامه کار اجازه دهید ابتدا تفاوت های object و primitive را بیان کنیم:
تفاوت آبجکت با انواع داده ای primitive:
مقایسه نوع داده ای آبجکت با نوع داده ای اولیه یا primitive.
Primitive:
تنها می تواند یک مقدار اولیه یا primitive در خود ذخیره کند. 7 نوع داده اولیه داریم: string, number, bigint, boolean, symbol, null و undefined
Object:
امکان ذخیره چندین نوع داده را در خود دارد. می تواند بوسیله {..} تعریف شود. مثلا {name: “John”, age: 30} در جاوا اسکریپت انواع دیگری از آبجکت نیز داریم. مثلا توابع (functions) هم نوعی آبجکت هستند.
یکی از بهترین امکانات آبجکت ها اینست که می توان یک یا چند تابع را بعنوان property آبجکت تعریف کرد.
let john = { name: "John", sayHi: function() { alert("Hi buddy!"); } }; john.sayHi(); // Hi buddy!
در مثال بالا یک آبجکت بنام john تعریف کردیم که شامل یک تابع sayHi است و یک property بنام name
یک primitive بعنوان object:
تناقضی که در جاوا اسکریپت برای استفاده از انواع primitive وجود دارد اینست که نیاز است متدهایی را روی این انواع داده فراخوانی کنیم (مثلا toUpperCase) در حالیکه ذات نوع داده اولیه بدین صورت است که باید سبک باشد.
پس نیاز است انواع اولیه در عین حال که سبک و تک مقدار هستند، برخی از امکانات آبجکت را نیز داشته باشند (مانند متدهای مذکور). در این حالت جاوا اسکریپت راه حل زیر را ارائه داده است:
- نوع داده primitive به همان شکل primitive و تک مقداری باقی می ماند.
- جاوا اسکریپت امکان دسترسی به متدها و property های مربوط به primitive ها (مانند string, number, boolean) را می دهد.
- به این منظور، یک object wrapper برای انواع اولیه یا primitive تعریف می شود و سپس حذف خواهد شد.
Object wrapper ها برای هریک از انواع داده اولیه (primitive types) متفاوت است و برای String و Number و Boolean و Symbol متدهای خاص آنها را فراهم می کند.
مثال:
let str = "Hello"; alert( str.toUpperCase() ); // HELLO
کارهایی که دقیقا در متد str.toUpperCase() انجام می شود به شکل زیر است:
- رشته str در مثال بالا از نوع primitive است و در هنگام فراخوانی متدها و property های آن، یک object wrapper برای آن تعریف می شود که مقدار آن رشته را در خود دارد بهمراه تمام متدهای مربوط به string مانند toUpperCase()
- متد مذکور اجرا می شود و رشته خروجی در alert نمایش می یابد.
- در نهایت پس از نمایش خروجی به کاربر آن object wrapper از رشته حذف می شود و به شکل همان primitive سابق بر می گردد.
بنابراین انواع داده اولیه یا primitive در عین حال که می توانند سبک (lightweight) باقی بمانند، امکان استفاده از متد را نیز دارند.
جاوا اسکریپت نوع number هم متدها و property های خودش را دارد. مانند toFixed
let n = 1.23456; alert( n.toFixed(2) ); // 1.23
متد toFixed(n) عدد موردنظر را به تعداد عدد دلخواه یعنی n رند می کند. عدد 1.23456 به عدد 1.23 تبدیل می شود.
نکته: انواع داده null/undefined در جاوا اسکریپت هیچ متدی ندارند. در واقع هیچ object wrapper ای برای داده های null و undefined تعریف نمی شود. بعنوان مثال کد زیر خطا می دهد:
alert(null.test); // error
نوع داده ای عددی (Numbers):
در زبان جاوا اسکریپت مدرن، دو نوع عدد داریم:
اعداد نرمال که با فرمت 64 بیتی ذخیره می شوند. در اکثر مواقع برنامه نویسان از این نوع عددی استفاده می کنند و بسیار رایج است.
اعداد BigInt: اگر عددی بزرگتر از 2 به توان 53 یا کوچکتر از 2 به توان 53- باشد باید از این نوع عددی در جاوا اسکریپت استفاده شود.
روش های مختلف تعریف عدد:
تصور کنید می خواهیم عدد یک میلیون را در متغیری ذخیره کنیم:
let billion = 1000000000;
در دنیای واقعی عدد یک میلیون را به صورت بالا نمی نویسیم زیرا احتمال اشتباه تایپی افزایش می یابد و نیز نوشتن یک میلیون با 6 تا صفر کمی سخت است! معمولا به شکل “یک میلیون” می نویسیم.
در جاوا اسکریپت می توانیم با استفاده از حرف e تعداد صفرهای عدد موردنظر را تعریف کنیم:
let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes alert( 7.3e9 ); // 7.3 billions (7,300,000,000)
مثال دیگر:
1e3 = 1 * 1000 1.23e6 = 1.23 * 1000000
حالا بیایید یک عدد بسیار کوچک را تعریف کنیم. یک میکرو ثانیه (یک میلیونیوم ثانیه!)
let ms = 0.000001;
الان متغیر بالا را توسط e تعریف می کنیم:
let ms = 1e-6; // six zeroes to the left from 1
مثالی دیگر:
// -3 divides by 1 with 3 zeroes 1e-3 = 1 / 1000 (=0.001) // -6 divides by 1 with 6 zeroes 1.23e-6 = 1.23 / 1000000 (=0.00000123)
اعداد هگز، باینری و اکتال:
از اعداد hex در جاوا اسکریپت استفاده زیادی می شود (مانند کد رنگی). فرمت تعریف آنها بدین صورت است که ابتدا 0x سپس عدد موردنظر را می نویسیم.
alert( 0xff ); // 255 alert( 0xFF ); // 255 (the same, case doesn't matter)
برای تعریف اعداد اکتال ابتدا 0o را تعریف کرده سپس عدد موردنظر.
برای تعریف اعداد باینری ابتدا 0b را تعریف کرده سپس عدد موردنظر.
let a = 0b11111111; // binary form of 255 let b = 0o377; // octal form of 255 alert( a == b ); // true, the same number 255 at both sides
متد (toString(base:
متد toString عدد موردنظر را به مبنای base می برد و سپس به رشته تبدیل می کند.
let num = 255; alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111
در مثال بالا، در خط دوم، عدد 255 به مبنای 16 رفته (ff) و به رشته تبدیل می شود. در خط سوم عدد 255 در مبنای 2 یعنی 11111111 به رشته تبدیل می شود و در alert نمایش می دهد.
نکته: عدد base می تواند از 2 تا 36 متغیر باشد. در حالت پیش فرض base برابر 10 است.
رند کردن اعداد (Round):
یکی از کاربردی ترین عملگرها هنگام کار با اعداد، رند کردن یا rounding می باشد.
چندین تابع پیش فرض برای رند کردن اعداد وجود دارد:
- Math.floor: عدد اعشاری را به پایین رند می کند. مثلا 1.1 به عدد 1 رند می شود و 1.1- به عدد 2- تبدیل می شود.
- Math.ceil: عدد اعشاری را به بالا رند می کند. مثلا 1.1 به عدد 2 رند می شود و 1.1- به عدد 1- تبدیل می شود.
- Math.round: به نزدیک ترین عدد صحیح (integer) رند می شود. مثلا 1.1 به 1 و 3.6 به 4 تبدیل خواهد شد.
- Math.trunc (توسط مرورگر IE پشتیبانی نمی شود): بخش صحیح را نگه می دارد و بخش اعشاری را حذف می کند.
مثال:
همانطور که قبلا ذکر کردیم برای اینکه تعداد دلخواهی از بخش اعشاری عدد را نگه داریم، می توان از متد toFixed استفاده کرد:
let num = 12.34; alert( num.toFixed(1) ); // "12.3"
سایر توابع ریاضی:
جاوا اسکریپت توابع پیش فرض (built-in) زیادی در زمینه ریاضی یا Math دارد.
Math.random:
بوسیله تابع Math.random() می توان یک عدد رندوم بین 0 و 1 تولید کرد:
alert( Math.random() ); // 0.1234567894322 alert( Math.random() ); // 0.5435252343232 alert( Math.random() ); // ... (any random numbers)
Math.max(a, b, c…) / Math.min(a, b, c…):
بزرگترین و کوچکترین عدد را از بین آرگومان های ارسالی پیدا می کند.
alert( Math.max(3, 5, -10, 0, 1) ); // 5 alert( Math.min(1, 2) ); // 1
Math.pow(n, power):
تابع pow عدد n را به توان power می رساند:
alert( Math.pow(2, 10) ); // 2 in power 10 = 1024
نوع داده ای رشته (Strings):
در جاوا اسکریپت داده های متنی بعنوان رشته یا string ذخیره می شود. برای ذخیره کاراکترهای تک حرفی نوع دیگری نداریم.
کوتیشن (Quotes):
رشته ها در جاوااسکریپت می توانند در داخل تک کوتیشن، دابل کوتیشن و بک تیک تعریف شوند:
let single = 'single-quoted'; let double = "double-quoted"; let backticks = `backticks`;
سینگل کوتیشن و دابل کوتیشن یکسان هستند اما بک تیک (backtick) یا ` متفاوت است. توسط آن می توان عبارات جاوا اسکریپتی داخل رشته تعریف کرد. (با استفاده از {…}). مثال:
function sum(a, b) { return a + b; } alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
کاربرد دیگر بک تیک (`) نمایش یک رشته در چند خط است:
let guestList = `Guests: * John * Pete * Mary `; alert(guestList); // a list of guests, multiple lines
اما اگر بخواهیم با سینگل یا دابل کوتیشن یک رشته را در چند خط بنویسیم ارور می دهد:
let guestList = "Guests: // Error: Unexpected token ILLEGAL * John";
کاراکترهای ویژه (Special characters):
برای اینکه بتوانید با استفاده از سینگل و دابل کوتیشن یک رشته را در چند خط نمایش دهید باید از “\n” استفاده کنید:
let guestList = "Guests:\n * John\n * Pete\n * Mary"; alert(guestList); // a multiline list of guests
بعنوان مثال دو دستور زیر یک خروجی یکسانی دارند:
let str1 = "Hello\nWorld"; // two lines using a "newline symbol" // two lines using a normal newline and backticks let str2 = `Hello World`; alert(str1 == str2); // true
مثال هایی با یونیکد (Unicode):
alert( "\u00A9" ); // © alert( "\u{20331}" ); // 佫, a rare Chinese hieroglyph (long unicode) alert( "\u{1F60D}" ); // 😍, a smiling face symbol (another long unicode)
تمام کاراکترهای ویژه با بک اسلش (\) شروع می شوند. کاربرد دیگر بک اسلش زمانیست که در رشته خود کوتیشن داشته باشیم:
alert( 'I\'m the Walrus!' ); // I'm the Walrus!
در کد بالا اگر از بک اسلش در تعریف رشته استفاده نشود جاوا اسکریپت تصور میکند تک کوتیشن پایان رشته است.
کاربرد دیگر بک تیک در موارد زیر است:
alert( `I'm the Walrus!` ); // I'm the Walrus!
همانطور که مشاهده می شود رشته تعریف شده توسط بک تیک دیگر نیازی به استفاده از بک اسلش ندارد.
اگر در رشته ما یک بک اسلش وجود دارد برای نمایش آن باید مطابق کد زیر از // استفاده شود:
alert( `The backslash: \\` ); // The backslash: \
طول رشته (String length):
با استفاده از پراپرتی length می توان طول رشته را فهمید:
alert( `My\n`.length ); // 3
نکته: در کد بالا، کاراکتر \n یک کاراکتر ویژه است و طولش یک است.
دقت کنید که length یک property عددی است. افرادی که سابقه برنامه نویسی با سایر زبان ها را دارند تصور می کنند length متد است و باید بصورت length() تعریف شود. در حالیکه این دستور خطا می دهد. نیازی به پرانتز نیست.
دسترسی به کاراکترهای رشته:
برای دسترسی به یک کاراکتر در پوزیشن pos می توان از [pos] یا str.charAt(pos) استفاده کرد. دقت کنید که اولین پوزشن 0 می باشد.
let str = `Hello`; // the first character alert( str[0] ); // H alert( str.charAt(0) ); // H // the last character alert( str[str.length - 1] ); // o
تنها تفاوت دو روش فوق برای دستیابی به یک کاراکتر در ایندکس موردنظر، اینست که اگر در براکت یعنی [pos] هیچ کاراکتری یافت نشود پیغام undefined می دهد و اگر در charAt(pos) کاراکتری پیدا نشود یک رشته خالی برمی گرداند.
let str = `Hello`; alert( str[1000] ); // undefined alert( str.charAt(1000) ); // '' (an empty string)
ما همچنین می توانیم با استفاده از ساختار for..of کاراکترهای یک رشته را در حلقه بکار ببریم:
for (let char of "Hello") { alert(char); // H,e,l,l,o (char becomes "H", then "e", then "l" etc) }
رشته ها تغییرناپذیرند:
دقت کنید که رشته ها یا strings در جاوا اسکریپت تغییر ناپذیرند. به این معنی که نمی توان کاراکترهای یک رشته را بطور مجزا ویرایش کرد و تغییر داد:
let str = 'Hi'; str[0] = 'h'; // error alert( str[0] ); // doesn't work
روشی که برای انجام اینکار پیشنهاد می شود اینست که یک رشته جدید تعریف شود و به متغیر str نسبت داده شود:
let str = 'Hi'; str = 'h' + str[1]; // replace the string alert( str ); // hi
بزرگ و کوچک کردن حروف رشته:
با استفاده از متدهای toLowerCase() و toUpperCase() می توان حروف یک رشته را در جاوا اسکریپت بزرگ (Upper Case) یا کوچک (Lower Case) کرد:
alert( 'Interface'.toUpperCase() ); // INTERFACE alert( 'Interface'.toLowerCase() ); // interface
اگر بخواهیم یک کاراکتر خاص را lower case کنیم، بصورت زیر عمل می کنیم:
alert( 'Interface'[0].toLowerCase() ); // 'i'
جستجوی یک زیر رشته (Substring):
در جاوا اسکریپت به روش های مختلفی می توان یک زیر رشته را در string پیدا کرد.
متد str.indexOf:
اولین متد str.indexOf(substr, pos) است. این متد بدنبال substr در رشته str می گردد (از ایندکس pos به بعد). اگر رشته مورد نظر پیدا شود، pos آن رشته برمی گردد و اگر زیر رشته substr در رشته str پیدا نشود، عدد 1- برمی گردد.
بعنوان مثال:
let str = 'Widget with id'; alert( str.indexOf('Widget') ); // 0, because 'Widget' is found at the beginning alert( str.indexOf('widget') ); // -1, not found, the search is case-sensitive alert( str.indexOf("id") ); // 1, "id" is found at the position 1 (..idget with id)
در مثال بالا آرگومان دوم یعنی pos تعریف نشده است زیرا اختیاری است و در صورت تعریف آن، کار جستجوی زیر رشته از پوزیشن تعریف شده تا انتهای رشته انجام می شود.
بعنوان مثال اولین جایی که در رشته widget with id کلمه id وجود دارد در پوزیشن 1 است. اما اگر بخواهیم پوزیشن بعدی کلمه id را پیدا کنیم باید آرگومان دوم متد را 2 تعریف کنیم:
let str = 'Widget with id'; alert( str.indexOf('id', 2) ) // 12
اگر بخواهیم تمام زیررشته های موجود در در رشته را پیدا کنیم باید متد indexOf را در یک حلقه بصورت زیر تعریف کنیم:
let str = 'As sly as a fox, as strong as an ox'; let target = 'as'; // let's look for it let pos = 0; while (true) { let foundPos = str.indexOf(target, pos); if (foundPos == -1) break; alert( `Found at ${foundPos}` ); pos = foundPos + 1; // continue the search from the next position }
در قطعه کد زیر الگوریتم بالا را به شکل خلاصه تر نوشتیم:
let str = "As sly as a fox, as strong as an ox"; let target = "as"; let pos = -1; while ((pos = str.indexOf(target, pos + 1)) != -1) { alert( pos ); }
نکته 1: توسط متد str.lastIndexOf(substr, position) می توان کار سرچ زیر رشته را از آخر به اول رشته انجام داد.
نکته 2: از متد indexOf نمی توان بصورت زیر در دستور شرطی if استفاده کرد:
let str = "Widget with id"; if (str.indexOf("Widget")) { alert("We found it"); // doesn't work! }
در مثال بالا، کلمه Widget در رشته str وجود دارد و ایندکس آن در رشته 0 است. پس داخل شرط if عدد صفر قرار می گیرد که یک مقدار falsy value است و شرط نادرست خواهد شد!
برای رفع این مشکل باید داخل شرط if حاصل جستجوی رشته را با عدد 1- مقایسه کرد:
let str = "Widget with id"; if (str.indexOf("Widget") != -1) { alert("We found it"); // works now! }
متدهای includes, startsWith, endsWith:
متد مدرن str.includes(substr, pos) اعلام می کند که آیا رشته مورد نظر در رشته مقصد وجود دارد یا خیر که خروجی آن true/false خواهد بود.
Includes گزینه مناسبی است برای مواقعی که فقط می خواهیم بدانیم آیا رشته موردنظرمان در رشته مقصد وجود دارد یا خیر و نیاز به پوزیشن رشته نداریم.
alert( "Widget with id".includes("Widget") ); // true alert( "Hello".includes("Bye") ); // false
متد includes هم شامل یک آرگومان اختیاری pos است که سرچ را از آن ایندکس به بعد انجام دهد:
alert( "Widget".includes("id") ); // true alert( "Widget".includes("id", 3) ); // false, from position 3 there is no "id"
متدهای startsWith و endsWith نیز دقیقا به همین صورت کار می کنند:
alert( "Widget".startsWith("Wid") ); // true, "Widget" starts with "Wid" alert( "Widget".endsWith("get") ); // true, "Widget" ends with "get"
گرفتن یک زیر رشته توسط متدهای slice و substr و substring:
در جاوا اسکریپت سه متد برای گرفتن یک زیر رشته از رشته موردنظر وجود دارد: substring, substr و slice
متد str.slice(start [, end]):
متد slice رشته موجود در پوزیشن start تا end را بر می گرداند. بعنوان مثال:
let str = "stringify"; alert( str.slice(0, 5) ); // 'strin', the substring from 0 to 5 (not including 5) alert( str.slice(0, 1) ); // 's', from 0 to 1, but not including 1, so only character at 0
اگر آرگومان دوم یعنی end تعریف نشود متد slice از start تا انتهای رشته را بر می گرداند.
مثال:
let str = "stringify"; alert( str.slice(2) ); // 'ringify', from the 2nd position till the end
تعریف آرگومان های start و end با مقادیر منفی نیز امکان پذیر می باشد:
let str = "stringify"; // start at the 4th position from the right, end at the 1st from the right alert( str.slice(-4, -1) ); // 'gif'
مقدار منفی در start و end به این معنیست که کار برش زیررشته از رشته اصلی از انتهای رشته انجام می شود.
متد str.substring(start [, end]):
تکه ای از رشته که بین start و end قرار دارد را به خروجی می دهد. تقریبا شبیه متد slice است با این تفاوت که مقدار آرگومان start می تواند از end بزرگتر باشد.
let str = "stringify"; // these are same for substring alert( str.substring(2, 6) ); // "ring" alert( str.substring(6, 2) ); // "ring" // ...but not for slice: alert( str.slice(2, 6) ); // "ring" (the same) alert( str.slice(6, 2) ); // "" (an empty string)
برخلاف متد slice، متد substring نمی تواند آرگومان های منفی داشته باشد. با آنها بعنوان عدد 0 رفتار می شود.
متد str.substr(start [, length]):
یک زیر رشته به طول length را که از پوزیشن start شروع می شود را بر می گرداند.
برخلاف متدهای قبلی، متد substr بجای آرگومان end تعداد کاراکترهای زیر رشته را می گیرد (length)
let str = "stringify"; alert( str.substr(2, 4) ); // 'ring', from the 2nd position get 4 characters
نکته: اولین آرگومان یعنی start می تواند منفی باشد. در اینصورت کار محاسبه نقطه شروع یعنی start index و برش رشته از انتهای رشته اصلی انجام می گیرد:
let str = "stringify"; alert( str.substr(-4, 2) ); // 'gi', from the 4th position get 2 characters
مقایسه رشته ها (Comparing strings):
همانطور که در فصل مقایسه ها گفتیم، رشته ها کاراکتر به کاراکتر و به ترتیب حروف الفبا با هم مقایسه می شوند.
موارد قابل ذکر:
همیشه حروف کوچک از حروف بزرگ، بزرگتر هستند:
alert( 'a' > 'Z' ); // true
حروفی که دو نقطه در بالای خود دارند از این قاعده مستثنی هستند:
alert( 'Österreich' > 'Zealand' ); // true
در کد بالا، احتمالا انتظار دارید حرف Ö از Z کوچکتر باشد. اما اینطور نیست!
متد str.codePointAt(pos):
کد کاراکتر را بر می گرداند:
// different case letters have different codes alert( "z".codePointAt(0) ); // 122 alert( "Z".codePointAt(0) ); // 90
دقت کنید که کد مربوط به حروف بزرگ و کوچک یک حرف خاص با هم متفاوت هستند.
متد string.fromCodePoint(code):
برای تولید یک کاراکتر بر اساس کد عددی آن بکار می رود:
alert( String.fromCodePoint(90) ); // Z
همچنین می توان با استفاده از \u و تعریف کد هگزادسیمال مربوط به کاراکتر، به حرف موردنظر رسید:
// 90 is 5a in hexadecimal system alert( '\u005a' ); // Z
اکنون می خواهیم کاراکترهای مربوط به کدهای 65 تا 220 را چاپ کنیم:
let str = ''; for (let i = 65; i <= 220; i++) { str += String.fromCodePoint(i); } alert( str ); // ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ // ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜ
همانطور که مشاهده می کنید ابتدا حروف بزرگ به خروجی رفته اند سپس حروف کوچک و سپس کاراکترهای خاص. بنابراین الان متوجه شدید که چرا a > Z می باشد.
نوع داده ای JSON:
نوع داده ای json یک فرمت متنی استاندارد است که مستقل از زبان برنامه نویسی می باشد و معمولا برای انتقال داده بین وب اپلیکیشن ها و پلتفرم های مختلف مورد استفاده قرار می گیرد.
JSON (JavaScript Object Notation) یک فرمت کلی برای ذخیره و نمایش آبجکت ها و مقادیر می باشد. Json اولین بار در زبان برنامه نویسی جاوا اسکریپت مطرح شد اما بتدریج اکثر زبان های برنامه نویسی کتابخانه هایی برای مدیریت JSON پیاده سازی کرده اند.
کاربرد اصلی JSON انتقال اطلاعات بین کلاینت و سرور است. کلاینت از جاوااسکریپت پشتیبانی می کند و سمت سرور هم می تواند توسط PHP-Python-ASP-JAVA یا هر زبان برنامه نویسی پیاده سازی شده باشد.
یکی از دلایل استفاده از JSON:
فرض کنید یک آبجکت پیچیده داریم و می خواهیم (مثلا به منظور لاگ گرفتن از آن یا ارسال آن به پلتفرم های دیگر) آن را به رشته تبدیل کنیم. طبیعتا این رشته باید شامل تمام property های آبجکت اصلی باشد. می توانیم این تبدیل را مطابق مثال زیر انجام دهیم:
let user = { name: "John", age: 30, toString() { return `{name: "${this.name}", age: ${this.age}}`; } }; alert(user); // {name: "John", age: 30}
اما اینکار مشکلات فراوان دارد. زیرا در حین اجرای برنامه ممکن است یک property جدید اضافه شود، نام یک property حذف شود یا یک property حذف شود. به روز کردن متد toString پس از هر تغییر می تواند اذیت کننده و وقت گیر باشد
جاوا اسکریپت توسط JSON این مشکل را حل کرده است.
متدهای جاوااسکریپت برای کار با JSON:
- JSON.stringify: برای تبدیل آبجکت به JSON
- JSON.parse: برای تبدیل JSON به آبجکت
متد JSON.stringify
در مثال زیر می خواهیم آبجکت student را به JSON تبدیل کنیم:
let student = { name: 'John', age: 30, isAdmin: false, courses: ['html', 'css', 'js'], wife: null }; let json = JSON.stringify(student); alert(typeof json); // we've got a string! alert(json); /* JSON-encoded object: { "name": "John", "age": 30, "isAdmin": false, "courses": ["html", "css", "js"], "wife": null } */
متد JSON.stringify(student) آبجکت را می گیرد و آن را به رشته تبدیل می کند. رشته JSON تولیدی به آبجکت JSON-encoded معروف است. اکنون می توان این رشته را به براحتی ارسال کرد یا آن را نمایش داد.
تفاوت های رشته معمولی با رشته JSON:
رشته ای که پس از تبدیل آبجکت به JSON تولید می شود با رشته معمولی که در خاطر داریم تفاوت هایی دارد.
- رشته JSON سینگل کوتیشن یا بک تیک ندارد بلکه دابل کوتیشن دارد. مثلا “John”
- نام property در رشته json باید درون دابل کوتیشن تعریف شود. مثلا “age”: 32
- متد JSON.stringify همچنین می تواند بر روی انواع اولیه داده (Primitive data types) اعمال شود.
JSON از انواع داده زیر پشتیبانی می کند:
Objects { ... } Arrays [ ... ] Primitives: strings, numbers, boolean values true/false, null.
مثال:
// a number in JSON is just a number alert( JSON.stringify(1) ) // 1 // a string in JSON is still a string, but double-quoted alert( JSON.stringify('test') ) // "test" alert( JSON.stringify(true) ); // true alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]
برخی از property ها و method های معمول آبجکت ها بهنگام تبدیل به رشته json نادیده گرفته می شوند:
- تمام متدها و فانکشن های آبجکت
- Property های سمبولیک
- Property هایی که undefined هستند.
let user = { sayHi() { // ignored alert("Hello"); }, [Symbol("id")]: 123, // ignored something: undefined // ignored }; alert( JSON.stringify(user) ); // {} (empty object)
مثال:
let user = { sayHi() { // ignored alert("Hello"); }, [Symbol("id")]: 123, // ignored something: undefined // ignored }; alert( JSON.stringify(user) ); // {} (empty object)
propertyهای تو در تو یا nested در آبجکت توسط رشته های json پشتیبانی می شود:
let meetup = { title: "Conference", room: { number: 23, participants: ["john", "ann"] } }; alert( JSON.stringify(meetup) ); /* The whole structure is stringified: { "title":"Conference", "room":{"number":23,"participants":["john","ann"]}, } */
آرگومان های JSON.stringify:
ساختار کامل متد stringify بصورت زیر است:
let json = JSON.stringify(value[, replacer, space])
- آرگومان value: مقداری که می خواهیم encode شود.
- آرگومان replacer: آرایه ای از property هایی که می خواهیم encode شوند یا تابع mapping بصورت function(key, value)
- آرگومان space: مقدار فضایی که می خواهیم برای فرمتدهی استفاده کنیم.
تعریف آرگومان دوم (replacer):
غالبا JSON.stringify با همان آرگومان اول فراخوانی می شود اما اگر بخواهیم دقیق تر کار کنیم می توانیم مانند مثال زیر عمل کنیم. در JSON.stringify(value, replacer, space) می خواهیم آرگومان دوم را شخصی سازی کنیم:
let room = { number: 23 }; let meetup = { title: "Conference", participants: [{name: "John"}, {name: "Alice"}], place: room // meetup references room }; room.occupiedBy = meetup; // room references meetup alert( JSON.stringify(meetup, ['title', 'participants']) ); // {"title":"Conference","participants":[{},{}]}
در مثال بالا برای تبدیل آبجکت به رشته json سختگیری کرده ایم و از آرگومان دوم متد stringify نیز استفاده کردیم. Property دوم یعنی participants برابر با یک آرایه خالی شده است زیرا name در لیست تعریف نشده است.
تعریف آرگومان سوم (space):
اکنون می خواهیم در متد JSON.stringify(value, replacer, space) آرگومان سوم یعنی space را تعریف کنیم. فاکتور space بیانگر تعداد فاصله ها در زیباسازی فرمت رشته json (pretty formatting) می باشد.
تا اینجا تمام رشته های json هیچگونه فاصله (space) و تورفتگی (indent) در آنها رعایت نشده بود. برای داشتن یک خروجی زیبا می توان از آرگومان space استفاده کرد:
let user = { name: "John", age: 25, roles: { isAdmin: false, isEditor: true } }; alert(JSON.stringify(user, null, 2)); /* two-space indents: { "name": "John", "age": 25, "roles": { "isAdmin": false, "isEditor": true } } */ /* for JSON.stringify(user, null, 4) the result would be more indented: { "name": "John", "age": 25, "roles": { "isAdmin": false, "isEditor": true } } */
در این مثال space = 2 تعریف شده است و به این معنیست که جاوا اسکریپت آبجکت های تو در تو را چندین خط زیر هم و با اعمال دو فاصله (indentation) از ابتدای سطر نمایش دهد.
متد JSON.parse:
برای دیکد کردن یک رشته json و تبدیل آن به یک آبجکت از متد JSON.parse استفاده می شود.
فرمت استفاده:
let value = JSON.parse(str, [reviver]);
- آرگومان str: رشته json ای که می خواهیم به آبجکت تبدیل شود.
- آرگومان reviver: بصورت function(key,value) و اختیاری است. برای تمام جفت مقادیر (key, value) اجرا می شود و می تواند آنها را تغییر دهد.
مثال:
// stringified array let numbers = "[0, 1, 2, 3]"; numbers = JSON.parse(numbers); alert( numbers[1] ); // 1
برای آبجکت های تو در تو:
let userData = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,2,3] }'; let user = JSON.parse(userData); alert( user.friends[1] ); // 1
به مثال زیر دقت کنید:
let json = `{ name: "John", // mistake: property name without quotes "surname": 'Smith', // mistake: single quotes in value (must be double) 'isAdmin': false // mistake: single quotes in key (must be double) "birthday": new Date(2000, 2, 3), // mistake: no "new" is allowed, only bare values "friends": [0,1,2,3] // here all fine }`;
JSON از کامنت پشتیبانی نمی کند. در صورت تعریف کامنت JSON نامعتبر (invalid) می شود.
در جلسه نهم از آموزش JAVAscript بطور مفصل درباره آرایه ها در js صحبت خواهیم کرد و تمام متدهای کاربردی آن را بهمراه مثال معرفی می کنیم.
دیدگاهتان را بنویسید