diff --git a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md index c63fe70cd..b3fa923aa 100644 --- a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md +++ b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md @@ -1,20 +1,20 @@ -# Rest parameters and spread syntax +# پارامترهای رست و سینتکس اسپرد -Many JavaScript built-in functions support an arbitrary number of arguments. +بسیاری از توابع جاوا‌اسکریپت از تعداد دلخواه آرگومان‌‌ها پشتیبانی می‌کنند. -For instance: +برای مثال: -- `Math.max(arg1, arg2, ..., argN)` -- returns the greatest of the arguments. -- `Object.assign(dest, src1, ..., srcN)` -- copies properties from `src1..N` into `dest`. -- ...and so on. +- `Math.max(arg1, arg2, ..., argN)` -- بزرگترین عدد میان آرگومان‌ها را برمی‌گرداند. +- `Object.assign(dest, src1, ..., srcN)` -- کپی می‌کند `src1..N` را در `dest`. +- ...و غیره. -In this chapter we'll learn how to do the same. And also, how to pass arrays to such functions as parameters. +در این فصل با نحوه انجام این کار آشنا می‌شویم. و همچنین نحوه انتقال آرایه به توابع به عنوان پارامتر(ها) را یاد خواهیم گرفت. -## Rest parameters `...` +## پارامترهای رست `...` -A function can be called with any number of arguments, no matter how it is defined. +یک تابع را می‌توان با هر تعداد آرگومان، صرف نظر از نحوه تعریف آن، فراخوانی کرد. -Like here: +مانند اینجا: ```js run function sum(a, b) { return a + b; @@ -23,14 +23,14 @@ function sum(a, b) { alert( sum(1, 2, 3, 4, 5) ); ``` -There will be no error because of "excessive" arguments. But of course in the result only the first two will be counted. +به دلیل آرگومان‌های بیش از اندازه هیچ خطایی وجود نخواهد داشت. البته در نتیجه فقط دو مورد اول محاسبه خواهند شد. -The rest of the parameters can be included in the function definition by using three dots `...` followed by the name of the array that will contain them. The dots literally mean "gather the remaining parameters into an array". +بقیه پارامترها را می‌توان با استفاده از سه نقطه `...` در قسمت تعریف تابع گنجاند و به دنبال آن نام آرایه ای که آنها را شامل است نوشت. نقاط به صورت تحت الفظی به معنی "جمع آوری پارامترهای باقی مانده (رست) در یک آرایه" است. -For instance, to gather all arguments into array `args`: +برای مثال، برای جمع آوری تمام آرگومان‌ها در آرایه `args`: ```js run -function sumAll(...args) { // args is the name for the array +function sumAll(...args) { // args نام آرایه است let sum = 0; for (let arg of args) sum += arg; @@ -43,41 +43,41 @@ alert( sumAll(1, 2) ); // 3 alert( sumAll(1, 2, 3) ); // 6 ``` -We can choose to get the first parameters as variables, and gather only the rest. +ما می‌توانیم اولین پارامترها را به عنوان متغیر دریافت کنیم و بقیه را جمع آوری کنیم. -Here the first two arguments go into variables and the rest go into `titles` array: +در اینجا دو آرگومان اول به متغیر و بقیه به آرایه `title` تبدیل می‌شوند: ```js run function showName(firstName, lastName, ...titles) { - alert( firstName + ' ' + lastName ); // Julius Caesar + alert( firstName + ' ' + lastName ); // پیام مرادی - // the rest go into titles array - // i.e. titles = ["Consul", "Imperator"] - alert( titles[0] ); // Consul - alert( titles[1] ); // Imperator + // پارامتر رست به آرایه "title" تبدیل می‌شود + // یعنی titles = ["مشاور", "امپراطور"] + alert( titles[0] ); // مشاور + alert( titles[1] ); // امپراطور alert( titles.length ); // 2 } -showName("Julius", "Caesar", "Consul", "Imperator"); +showName("پیام", "مرادی", "مشاور", "امپراطور"); ``` -````warn header="The rest parameters must be at the end" -The rest parameters gather all remaining arguments, so the following does not make sense and causes an error: +````warn header="پارامترهای رست باید در انتها باشند" +پارامترهای رست همه آرگومان‌های باقی مانده را جمع آوری می‌کنند، بنابراین موارد زیر منطقی نیستند و باعث ایجاد خطا می‌شوند: ```js -function f(arg1, ...rest, arg2) { // arg2 after ...rest ?! - // error +function f(arg1, ...rest, arg2) { // arg2 بعد از ...rest ?! + // ارور } ``` -The `...rest` must always be last. +`...rest` همیشه باید در آخر باشد. ```` -## The "arguments" variable +## متغیر "arguments" -There is also a special array-like object named `arguments` that contains all arguments by their index. +همچنین یک شی آرایه مانند ویژه به نام `arguments` وجود دارد که شامل همه آرگومان‌ها بر اساس ترتیب فهرست آنها است. -For instance: +برای مثال: ```js run function showName() { @@ -85,29 +85,29 @@ function showName() { alert( arguments[0] ); alert( arguments[1] ); - // it's iterable + // قابل تکرار است // for(let arg of arguments) alert(arg); } -// shows: 2, Julius, Caesar -showName("Julius", "Caesar"); +// نشان می‌دهد: 2, پیام, مرادی +showName("پیام", "مرادی"); -// shows: 1, Ilya, undefined (no second argument) -showName("Ilya"); +// نشان می‌دهد: 1, ایلیا, undefined (آرگومان دوم وجود ندارد) +showName("ایلیا"); ``` -In old times, rest parameters did not exist in the language, and using `arguments` was the only way to get all arguments of the function. And it still works, we can find it in the old code. +در زمان های قدیم، ویژگی پارامترهای رست در زبان جاوااسکریپت وجود نداشت و استفاده از "arguments" تنها راه بدست آوردن همه آرگومان‌‌های تابع بود. و هنوز کار می‌کند، می‌توانیم آن را در کد‌های قدیمی پیدا کنیم. -But the downside is that although `arguments` is both array-like and iterable, it's not an array. It does not support array methods, so we can't call `arguments.map(...)` for example. +اما نکته منفی این است که اگرچه `arguments` هم آرایه مانند است و هم قابل تکرار، اما یک آرایه نیست. از متد‌‌های آرایه پشتیبانی نمی‌کند، بنابراین نمی‌توانیم به عنوان مثال `arguments.map(...)` را فراخوانی کنیم. -Also, it always contains all arguments. We can't capture them partially, like we did with rest parameters. +همچنین همیشه شامل همه آرگومان‌‌ها است. ما نمی‌توانیم تعداد مشخصی از آنها را به دست بیاوریم، مانند کاری که با پارامتر‌های رست انجام دادیم. -So when we need these features, then rest parameters are preferred. +بنابراین وقتی به این ویژگی‌ها نیاز داریم، پارامترهای رست ترجیح داده می‌شود. -````smart header="Arrow functions do not have `\"arguments\"`" -If we access the `arguments` object from an arrow function, it takes them from the outer "normal" function. +````smart header="توابع تک خطی شی `\"arguments\"` ندارند" +اگر از یک تابع تک خطی به شی `arguments` دسترسی پیدا کنیم، آنها را از تابع "عادی" بیرونی خارج می‌کند. -Here's an example: +در اینجا یک مثال وجود دارد: ```js run function f() { @@ -118,49 +118,49 @@ function f() { f(1); // 1 ``` -As we remember, arrow functions don't have their own `this`. Now we know they don't have the special `arguments` object either. +همانطور که به خاطر داریم، توابع تک خطی از خود `this` ندارند. اکنون می‌دانیم که آنها شی `arguments` خاصی نیز ندارند. ```` -## Spread syntax [#spread-syntax] +## سینتکس اسپرد [#spread-syntax] -We've just seen how to get an array from the list of parameters. +ما فقط نحوه گرفتن یک آرایه از لیست پارامترها را دیدیم. -But sometimes we need to do exactly the reverse. +اما گاهی اوقات ما باید دقیقاً برعکس عمل کنیم. -For instance, there's a built-in function [Math.max](mdn:js/Math/max) that returns the greatest number from a list: +برای مثال، یک تابع داخلی [Math.max](mdn:js/Math/max) وجود دارد که بیشترین عدد را از یک لیست بر می‌گرداند: ```js run alert( Math.max(3, 5, 1) ); // 5 ``` -Now let's say we have an array `[3, 5, 1]`. How do we call `Math.max` with it? +حالا فرض کنید یک آرایه داریم `[3, 5, 1]`. چگونه با آن تابع `Math.max` را فراخوانی کنیم؟ -Passing it "as is" won't work, because `Math.max` expects a list of numeric arguments, not a single array: +وارد کردن آن "همانطور که هست" کار نخواهد کرد، زیرا `Math.max` لیستی از آرگومان های عددی را انتظار دارد، نه یک آرایه واحد: ```js run let arr = [3, 5, 1]; *!* alert( Math.max(arr) ); // NaN -*/!* +*/!* ``` -And surely we can't manually list items in the code `Math.max(arr[0], arr[1], arr[2])`, because we may be unsure how many there are. As our script executes, there could be a lot, or there could be none. And that would get ugly. +و مطمئناً ما نمی‌توانیم مواردی را در تابع `Math.max(arr[0], arr[1], arr[2])` به صورت دستی لیست کنیم، زیرا ممکن است مطمئن نباشیم تعداد آنها چقدر است. همانطور که اسکریپت ما اجرا می‌شود، ممکن است تعداد زیادی (آرگومان) وجود داشته باشد، یا ممکن است وجود نداشته باشد. و این باعث زشتی کد ما می‌شود. -*Spread syntax* to the rescue! It looks similar to rest parameters, also using `...`, but does quite the opposite. +*سینتکس اسپرد* برای نجات! شبیه به پارامترهای رست به نظر می‌رسد، همچنین از `...` استفاده می‌کند، اما کاملا متفاوت است. -When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments. +هنگامی که از `...arr` در فراخوانی تابع استفاده می‌شود، یک شی `arr` قابل تکرار را در لیست آرگومان‌ها قرار می‌دهد. -For `Math.max`: +برای `Math.max`: ```js run let arr = [3, 5, 1]; -alert( Math.max(...arr) ); // 5 (spread turns array into a list of arguments) +alert( Math.max(...arr) ); // 5 (سینتکس اسپرد یک آرایه را به لیستی از آرگومان‌ها تبدیل می‌کند) ``` -We also can pass multiple iterables this way: +همچنین می‌توان چند مورد قابل تکرار را از این طریق به عنوان آرگومان به تابع انتقال داد: ```js run let arr1 = [1, -2, 3, 4]; @@ -169,7 +169,7 @@ let arr2 = [8, 3, -8, 1]; alert( Math.max(...arr1, ...arr2) ); // 8 ``` -We can even combine the spread syntax with normal values: +حتی می‌توان سینتکس اسپرد را با مقادیر معمولی ترکیب کرد: ```js run @@ -179,7 +179,7 @@ let arr2 = [8, 3, -8, 1]; alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25 ``` -Also, the spread syntax can be used to merge arrays: +همچنین سینتکس اسپرد می‌تواند برای ادغام آرایه‌ها استفاده شود: ```js run let arr = [3, 5, 1]; @@ -189,107 +189,107 @@ let arr2 = [8, 9, 15]; let merged = [0, ...arr, 2, ...arr2]; */!* -alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2) +alert(merged); // 0,3,5,1,2,8,9,15 (0, سپس arr, سپس 2, سپس arr2) ``` -In the examples above we used an array to demonstrate the spread syntax, but any iterable will do. +در مثال‌های بالا ما از آرایه برای نشان دادن سینتکس اسپرد استفاده کردیم، اما برای هر مورد قابل تکرار قابل استفاده است -For instance, here we use the spread syntax to turn the string into array of characters: +برای مثال، در اینجا از سینتکس اسپرد برای تبدیل رشته به آرایه ای از کاراکترها استفاده می‌کنیم: ```js run -let str = "Hello"; +let str = "سلام"; -alert( [...str] ); // H,e,l,l,o +alert( [...str] ); // س, ل, ا, م ``` -The spread syntax internally uses iterators to gather elements, the same way as `for..of` does. +سینتکس اسپرد به صورت داخلی از تکرارکنندگان برای جمع آوری المنت‌‌ها استفاده می‌کند، همانطور که `for..of` این کار را انجام می‌دهد. -So, for a string, `for..of` returns characters and `...str` becomes `"H","e","l","l","o"`. The list of characters is passed to array initializer `[...str]`. +بنابراین، برای یک رشته، `for..of` کاراکترها را برمی‌گرداند و با استفاده از `...str` به "س"، "ل"، "ا"، "م ` تبدیل می‌شود. لیست کاراکترها به تنظیم کننده آرایه `[...str]` منتقل می‌شود. -For this particular task we could also use `Array.from`, because it converts an iterable (like a string) into an array: +برای این کار خاص همچنین می‌توانیم از `Array.from` استفاده کنیم، زیرا یک تکرار شونده (مانند یک رشته) را به یک آرایه تبدیل می‌کند: ```js run let str = "Hello"; -// Array.from converts an iterable into an array -alert( Array.from(str) ); // H,e,l,l,o +// Array.from یک قابل تکرار را به آرایه تبدیل می‌کند +alert( Array.from(str) ); // س, ل, ا, م ``` -The result is the same as `[...str]`. +نتیجه مانند نتیجه هنگام استفاده از `[...str]` است. -But there's a subtle difference between `Array.from(obj)` and `[...obj]`: +اما بین `Array.from(obj)` و `[...obj]` یک تفاوت ظریف وجود دارد: -- `Array.from` operates on both array-likes and iterables. -- The spread syntax works only with iterables. +- `Array.from` هم بر روی "آرایه مانند" و هم بر روی "تکرار شونده" کار می‌کند. +- سینتکس اسپرد فقط بر روی "تکرار شونده‌ها" کار می‌کند. -So, for the task of turning something into an array, `Array.from` tends to be more universal. +بنابراین، برای تبدیل چیزی به یک آرایه، `Array.from` بیشتر جهانی است. -## Copy an array/object +## کپی کردن یک آرایه/شی -Remember when we talked about `Object.assign()` [in the past](info:object-copy#cloning-and-merging-object-assign)? +زمانی که ما در مورد `Object.assign()` [در گذشته صحبت کردیم را به یاد دارید](info:object-copy#cloning-and-merging-object-assign)? -It is possible to do the same thing with the spread syntax. +انجام همان کار با سینتکس اسپرد امکان پذیر است. ```js run let arr = [1, 2, 3]; *!* -let arrCopy = [...arr]; // spread the array into a list of parameters - // then put the result into a new array +let arrCopy = [...arr]; // یک آرایه را به لیستی از پارامترها گسترش می‌دهد + // سپس نتیجه را در یک آرایه جدید قرار می‌دهد */!* -// do the arrays have the same contents? +// آیا آریه‌ها محتوای یکسانی دارند؟ alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true -// are the arrays equal? -alert(arr === arrCopy); // false (not same reference) +// آیا آرایه‌ها برابر هستند؟ +alert(arr === arrCopy); // false (مرجع یکسان نیست) -// modifying our initial array does not modify the copy: +// اصلاح آرایه اولیه باعث ایجاد تغییر در کپی نمی‌شود: arr.push(4); alert(arr); // 1, 2, 3, 4 alert(arrCopy); // 1, 2, 3 ``` -Note that it is possible to do the same thing to make a copy of an object: +توجه داشته باشید که برای ایجاد یک کپی از یک شی می‌توان همان کار را انجام داد: ```js run let obj = { a: 1, b: 2, c: 3 }; *!* -let objCopy = { ...obj }; // spread the object into a list of parameters - // then return the result in a new object +let objCopy = { ...obj }; // شی را به لیستی از پارامترها گسترش می‌دهد + // سپس نتیجه را در یک شی جدید برمی‌گرداند */!* -// do the objects have the same contents? +// آیا شی‌ها محتوای یکسانی دارند؟ alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true -// are the objects equal? -alert(obj === objCopy); // false (not same reference) +// آیا شی‌ها برابر هستند؟ +alert(obj === objCopy); // false (مرجع یکسان نیست) -// modifying our initial object does not modify the copy: +// اصلاح شی اولیه باعث ایجاد تغییر در شی کپی‌شده نمی‌شود: obj.d = 4; alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4} alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3} ``` -This way of copying an object is much shorter than `let objCopy = Object.assign({}, obj)` or for an array `let arrCopy = Object.assign([], arr)` so we prefer to use it whenever we can. +این روش کپی کردن یک شی بسیار کوتاه‌تر از `let objCopy = Object.assign({}, obj)` و یا برای یک آرایه `let arrCopy = Object.assign([], arr)` است، بنابراین ما ترجیح می‌دهیم هر زمان که می‌توانیم از آن استفاده کنیم. -## Summary +## خلاصه -When we see `"..."` in the code, it is either rest parameters or the spread syntax. +هنگامی که در کد `"..."` را می‌بینیم، این عبارت یا پارامترهای رست است یا سینتکس اسپرد. -There's an easy way to distinguish between them: +یک راه آسان برای تشخیص تمایز بین آنها وجود دارد: -- When `...` is at the end of function parameters, it's "rest parameters" and gathers the rest of the list of arguments into an array. -- When `...` occurs in a function call or alike, it's called a "spread syntax" and expands an array into a list. +- وقتی `...` در انتهای پارامترهای تابع قرار دارد، "پارامترهای رست" است و بقیه لیست آرگومان‌ها را در یک آرایه جمع آوری می‌کند. +- وقتی `...` در فراخوانی یک تابع یا در موقعیت مانند آن نوشته می‌شود، آن را" سینتکس اسپرد "می‌نامند و یک آرایه را به یک لیست گسترش می‌دهد. -Use patterns: +از الگو‌ها استفاده کنید: -- Rest parameters are used to create functions that accept any number of arguments. -- The spread syntax is used to pass an array to functions that normally require a list of many arguments. +- پارامترهای رست برای ایجاد توابعی که هر تعداد آرگومان را بپذیرند استفاده می‌شوند. +- سینتکس اسپرد برای انتقال یک آرایه به توابعی که معمولاً به لیستی از آرگومان‌ها نیاز دارند، استفاده می‌شود. -Together they help to travel between a list and an array of parameters with ease. +آنها با هم کمک می‌کنند به جابه‌جایی آسان بین یک لیست و یک آرایه از پارامترها. -All arguments of a function call are also available in "old-style" `arguments`: array-like iterable object. +تمام آرگومان های یک فراخوانی تابع نیز در "سبک قدیمی" `arguments`: شی آرایه مانند قابل تکرار، موجود است.