38 - جاوااسکریپت: Arrays, Collections of Anything

آرایه یک مجموعه است. برای تعریف آرایه میتوانیم از دستور زیر استفاده کنیم:var arr = new Array();این روش طولانی برای تعریف آرایه است. میتوانیم از array literal syntax استفاده کنیم:var arr = [ ];در js آرایه ها کمی متفاوت هستند. چون js م dynamically typed است. در اکثر زبان های برنامه نویسی آرایه میتواند مجموعه ای از داده ها با یک نوع خاص باشد. ولی js اینطور نیست و نوع چیزها را on the fly میفهمد. پس میتوانیم هرچه میخواهیم داخل آرایه بگذاریم و آنها را مخلوط بگذاریم:var arr = [ 1, false, {name:'Tony',address:'Main 111 St'}, function(name){console.log(name);}, "hello"];تابعی که در آرایه بالا گذاشته یک expression است چون فقط خودش تنها نیست و داخل تعریف آرایه است. js میفهمد که باید این تابع را on the fly ایجاد کند. اگر کنسول arr را ببینیم:[1, false, Object, function, "hello"]در این مثال اگر بخواهیم تابع را اجرا کنیم:arr[3](arr[2].name);خروجی میشه Tony. پس آرایه ها حتی میتونن شامل تابع هم باشن. این ویژگی میتواند مفید باشد.39 - جاوااسکریپت: arguments, spreadوقتی تابعی را اجرا میکنیم، موتور js کلمه کلیدی arguments رو به صورت اتوماتیک ست میکنه. چون در نسخه بعدی js زیاد از arguments استفاده نمیشود، روش جدید را که SPREAD نام دارد معرفی میکنیم.اگر به هر کدی در framework ها یا کتابخانه ها نگاه کنیم، متغیرهای arguments را میبینیم.زمانی که تابعی را اجرا میکنیم یک execution context جدید ایجاد میشود و موتور js چیزهایی را برای ما تنظیم میکند، مثل variable environment که همه متغیرها را نگه میدارد و outer environment reference برای scope chain و کلمه کلیدی this که به محل قرار گرفتن تابع و چگونگی فراخوانی آن ارتباط دارد. به غیر از اینها کلمه کلیدی دیگری را هم به نام arguments تنظیم میکند. arguments شامل یک لیست است از همه مقادیر و همه پارامترهایی که به یک تابع پاس میدهیم. یعنی arguments همه آن مقادیری را که به تابعی پاس میدهیم نگه میدارد.تعریف arguments: مفهوم آن در حالت کلی پارامترهایی است که به یک تابع پاس میدهیم. در js از کلمه کلیدی با همین نام استفاده میشود و همه آنها را شامل میشود. پس وقتی در مورد مفهوم arguments صحبت میکنیم فقط در مورد پارامترهایی که به تابع پاس داده میشود صحبت میکنیم. اما کلمه کلیدی arguments را js ایجاد کرده است.function greet(firsname, lastname, language) {console.log(firstname);console.log(lastname);console.log(language);}آنچه در js متفاوت است این است که میتوانیم تابع بالا را فقط با کد زیر فراخوانی کنیم و هیچ پارامتری به آن پاس ندهیم:greet();در زبان های برنامه نویسی دیگر این کار خطا میدهد. خروجی میشود:undefinedundefinedundefinedبنابراین hoisting آنچه با اجرای تابع اتفاق می افتد یا مقادیر را تنظیم میکند، از این پارامترها مراقبت میکند با اینکه ما هیچ مقداری بهش ندادیم. تابع greet را اجرا میکند و اولین کاری که میکند این است که فضایی از حافظه را برای firstname و lastname و language تنظیم کند و آنها را undefined بگذارد. js به این موضوع که ما هیچ مقداری به تابع ندادیم اهمیتی نمیدهد، همچنان فضای حافظه را تنظیم میکند و آن را undefined میگذارد.اگر به تابع arguments را بدهیم، از چپ به راست پردازش میشوند. پس اگر داشته باشیم:greet('John'); فرض میکند که 'John' همان firstname است و برای lastname و language چیزی پاس نداده ایم و این دو را همان undefined میگذارد.پس میتوانیم پاس دادن پارامتر به تابع را skip کنیم یا میتوانیم بخشی از لیست پارامترها را skip کنیم و js مشکلی با این کار ندارد. در نسل بعدی js این امکان را داریم که مقدار پیش فرض برای پارامترها قرار دهیم. یعنی بهش بگیم اگر مقداری داده نشد آن مقدار پیش فرض را در نظر بگیرد:function greet(firsname, lastname, language = 'en') { ... }اما این روش هنوز در همه بروزرها قابل استفاده نیست، پس میتوانیم از مفهوم پارامتر پیش فرض استفاده کنیم:function greet(firsname, lastname, language) {language = language || 'en';...}پس اگر language مقدار undefined داشته باشد و به عملگر || پاس داده شود، به false م coerce میشود و 'en' به عملگر = پاس داده میشود. در این حالت اگر داشته باشیم:greet();خروجی میدهد:undefinedundefinedenو اگر داشته باشیم:greet('John', 'Doe', 'es');خروجی میدهد:JohnDoeesپس با این روش مقدار پیش فرض را تعیین کردیم ولی در نسخه جدید js میتوانیم مقدار پیش فرض را همون بالا جلوی پارامتر بگذاریم.کلمه کلیدی arguments را js تنظیم کرده و نیازی به تعریف کردن ندارد و قابل دسترس است. اگر داخل تابع بالا اضافه کنیم:function greet(firsname, lastname, language) {console.log(arguments);}اگر بگوییم greet(); خروجی [ ] را میدهد. اگر بگوییم greet('John); خروجی ['John'] را میدهد. اگر بگوییم greet('John', 'Doe', 'es'); خروجی ['John', 'Doe', 'es'] را میدهد. یعنی شامل لیستی از همه مقادیر پارامتری است که پاس داده ایم. نحوه نمایش آن شبیه به آرایه است ولی آرایه نیست و در ظاهر هم ایتالیک است و براکت نیست. به آن array-like میگوییم. یعنی شبیه به آرایه عمل میکند و ظاهرا شبیه به آرایه است ولی دقیقا یک آرایه نیست. مثلا همه ویژگی های آرایه js را ندارد. اما در خیلی از شرایط میتوانیم مثل آرایه با آن رفتار کنیم. برای مثال اگر بخواهیم وقتی پارامتری پاس داده نمیشود تابع کاری نکند، میتوانیم به اول کد تابع این را اضافه کنیم:function greet(firsname, lastname, language) {if (argument.length===0) { console.log('missing parameters');return; }...}پس میتوانیم بسته به تعداد آرگومانهایی که پاس داده شده اند کار خاصی انجام دهیم. اگرچه آرگومانها شامل اسم نیستند و فقط مقدار دارند، میتوانیم مثل یک آرایه از براکت استفاده کنیم و position آرگومان رو بدهیم:console.log(arguments[0]);اگر بگوییم greet('John'); خروجی John را میدهد.هنوز arguments هنوز وجود دارد اما بهترین روش برای انجام یک کار نیست. چیز جدید پارامتر spread است. یعنی اگر پارامترهایی را که به تابع پاس داده ایم داشته باشیم، میتوانیم یک پارامتر را با فرمت ...name به آخر پارامترهای تابع اضافه کنیم:function greet(firsname, lastname, language, ...other) { ... }اگر موقع فراخوانی این تابع پارامترهای بیشتری به تابع پاس دهیم، مثل:greet('John, 'Doe', 'ed', 'Main 111 St', 'New York');این دو پارامتر اضافه که صریحا تعریف نشده اند، در یک آرایه wrap میشوند. پس ...other یعنی همه چیز اضافی را بگیر و در یک آرایه با اسم other م wrap کن. البته این روش هم هنوز به طور کامل در دسترس نیست. ولی زمانی که در دسترس باشد، روش مناسبتری برای کار کردن با آرگومانهای متنوع است. اما هنوز از arguments استفاده های زیادی میشود.