diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
index d5a09efb3..5bb97f442 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/_js.view/solution.js
@@ -1,7 +1,7 @@
function spy(func) {
function wrapper(...args) {
- // using ...args instead of arguments to store "real" array in wrapper.calls
+ // wrapper.calls برای ذخیره کردن آرایه «واقعی» درون arguments به جای ...args استفاده از
wrapper.calls.push(args);
return func.apply(this, args);
}
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
index 0c8a211b4..504d6268e 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/solution.md
@@ -1 +1 @@
-The wrapper returned by `spy(f)` should store all arguments and then use `f.apply` to forward the call.
+دربرگیرنده که توسط `spy(f)` برگردانده میشود باید تمام آرگومانها را ذخیره و سپس از `f.apply` برای ارسال کردن فراخوانی استفاده کند.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
index a3843107c..ac75c834b 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/01-spy-decorator/task.md
@@ -2,17 +2,17 @@ importance: 5
---
-# Spy decorator
+# دکوراتور جاسوس
-Create a decorator `spy(func)` that should return a wrapper that saves all calls to function in its `calls` property.
+یک دکوراتور `spy(func)` بسازید که باید دربرگیرندهای را برگرداند که تمام فراخوانیهای تابع را درون ویژگی `calls` خودش ذخیره کند.
-Every call is saved as an array of arguments.
+هر فراخوانی به عنوان آرایهای از آرگومانها ذخیره میشود.
-For instance:
+برای مثال:
```js
function work(a, b) {
- alert( a + b ); // work is an arbitrary function or method
+ alert( a + b ); // یک تابع یا متد داخواه است work تابع
}
*!*
@@ -27,4 +27,4 @@ for (let args of work.calls) {
}
```
-P.S. That decorator is sometimes useful for unit-testing. Its advanced form is `sinon.spy` in [Sinon.JS](http://sinonjs.org/) library.
+پینوشت: این دکوراتور بعضی اوقات در انجام یونیت تست (unit-testing) کاربرد دارد. شکل پیشرفته آن `sinon.spy` در کتابخانه [Sinon.JS](http://sinonjs.org/) است.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
index 44b5024e1..56505a65e 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/solution.md
@@ -1,4 +1,4 @@
-The solution:
+راهحل:
```js
function delay(f, ms) {
@@ -10,14 +10,14 @@ function delay(f, ms) {
}
```
-Please note how an arrow function is used here. As we know, arrow functions do not have own `this` and `arguments`, so `f.apply(this, arguments)` takes `this` and `arguments` from the wrapper.
+لطفا به چگونگی استفاده از تابع کمانی در اینجا توجه کنید. همانطور که میدانیم، تابعهای کمانی `this` و `arguments` خودشان را ندارند پس `f.apply(this, arguments)` مقدار `this` و `arguments` را از دربرگیرنده میگیرند.
-If we pass a regular function, `setTimeout` would call it without arguments and `this=window` (in-browser), so we'd need to write a bit more code to pass them from the wrapper:
+اگر ما یک تابع معمولی را قرار دهیم، `setTimeout` آن را بدون آرگومانها و `this=window` (در مرورگر) فراخوانی خواهد کرد، پس ما باید کمی بیشتر کد بنویسیم تا آنها از طریق دربرگیرنده رد و بدل کنیم:
```js
function delay(f, ms) {
- // added variables to pass this and arguments from the wrapper inside setTimeout
+ // قرار دهیم setTimeout و آرگومانها را از طریق دربرگیرنده درون this متغیرهایی اضافه کردیم تا
return function(...args) {
let savedThis = this;
setTimeout(function() {
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md
index c04c68d7e..10b6bf538 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/02-delay/task.md
@@ -2,11 +2,11 @@ importance: 5
---
-# Delaying decorator
+# دکوراتور تأخیر انداز
-Create a decorator `delay(f, ms)` that delays each call of `f` by `ms` milliseconds.
+یک دکوراتور `delay(f, ms)` بسازید که هر فراخوانی `f` را به اندازه `ms` میلیثانیه به تأخیر میاندازد.
-For instance:
+برای مثال:
```js
function f(x) {
@@ -17,10 +17,10 @@ function f(x) {
let f1000 = delay(f, 1000);
let f1500 = delay(f, 1500);
-f1000("test"); // shows "test" after 1000ms
-f1500("test"); // shows "test" after 1500ms
+f1000("test"); // را بعد از 1000 میلیثانیه نشان میدهد "test"
+f1500("test"); // را بعد از 1500 میلیثانیه نشان میدهد "test"
```
-In other words, `delay(f, ms)` returns a "delayed by `ms`" variant of `f`.
+به عبارتی دیگر، `delay(f, ms)` یک نوع از `f` که «به اندازه `ms` تأخیر دارد» را برمیگرداند.
-In the code above, `f` is a function of a single argument, but your solution should pass all arguments and the context `this`.
+در کد بالا، `f` تایعی است که یک آرگومان دارد اما راهحل شما باید تمام آرگومانها و زمینه `this` را در فراخوانی قرار دهد.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
index e3b4d5842..e833da109 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/debounce.view/index.html
@@ -1,18 +1,18 @@
-Function handler is called on this input:
+تابع handler روی این ورودی فراخوانی میشود:
-
+
-Debounced function debounce(handler, 1000) is called on this input:
+تابع معلق debounce(handler, 1000) روی این ورودی فراخوانی میشود:
-
+
-
+
\ No newline at end of file
+
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
index 83e75f315..8a38db78d 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/solution.md
@@ -9,5 +9,5 @@ function debounce(func, ms) {
```
-A call to `debounce` returns a wrapper. When called, it schedules the original function call after given `ms` and cancels the previous such timeout.
+فراخوانی `debounce` یک دربرگیرنده را برمیگرداند. زمانی که فرا خوانده شد، زمانبندی میکند که تابع اصلی بعد از مدت `ms` داده شده فراخوانی شود و زمانبندی قبلی را لغو میکند.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
index 5b0fcc5f8..5841db003 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/03-debounce/task.md
@@ -2,21 +2,21 @@ importance: 5
---
-# Debounce decorator
+# دکوراتور معلقکننده
-The result of `debounce(f, ms)` decorator is a wrapper that suspends calls to `f` until there's `ms` milliseconds of inactivity (no calls, "cooldown period"), then invokes `f` once with the latest arguments.
+نتیجه دکوراتور `debounce(f, md)` یک دربرگیرنده است که تا `ms` میلیثانیه عدم فعالیت وجود نداشته باشد، فراخوانیهای `f` را به حالت تعلیق در میآورد (فراخوانی انجام نمیشود، «مدت زمان آرامشدن») سپس `f` را با آخرین آرگومانها فراخوانی میکند.
-In other words, `debounce` is like a secretary that accepts "phone calls", and waits until there's `ms` milliseconds of being quiet. And only then it transfers the latest call information to "the boss" (calls the actual `f`).
+به عبارتی دیگر، `debounce` مانند یک منشی است که «تماسهای تلفنی» را میپذیرد و تا زمانی که `ms` میلیثانیه سکوت برقرار شود صبر میکند. و فقط بعد از این مدت اطلاعات آخرین تماس را به «رئیس» منتقل میکند (تابع واقعی `f` را فرا میخواند).
-For instance, we had a function `f` and replaced it with `f = debounce(f, 1000)`.
+برای مثال، ما یک تابع `f` داشتیم و آن را با `f = debounce(f, 1000)` جایگزین کردیم.
-Then if the wrapped function is called at 0ms, 200ms and 500ms, and then there are no calls, then the actual `f` will be only called once, at 1500ms. That is: after the cooldown period of 1000ms from the last call.
+سپس اگر تابع دربرگرفته شده در زمانهای 0، 200، 500 میلیثانیه فراخوانی شد، و پس از آن هیچ فراخوانیای وجود نداشت، سپس تابع واقعی `f` فقط یک بار بعد از 1500 میلیثانیه فراخوانی میشود. یعنی اینکه: پس از 1000 میلیثانیه زمان آرامشدن از زمان آخرین فراخوانی.

-...And it will get the arguments of the very last call, other calls are ignored.
+...و این تابع آرگومانهای آخرین فراخوانی را دریافت میکند و بقیه فراخوانیها نادیده گرفته میشوند.
-Here's the code for it (uses the debounce decorator from the [Lodash library](https://lodash.com/docs/4.17.15#debounce)):
+اینجا کدی برای آن داریم (از دکوراتور معلقکننده در کتابخانه [Lodash library](https://lodash.com/docs/4.17.15#debounce) استفاده میکند):
```js
let f = _.debounce(alert, 1000);
@@ -24,28 +24,28 @@ let f = _.debounce(alert, 1000);
f("a");
setTimeout( () => f("b"), 200);
setTimeout( () => f("c"), 500);
-// debounced function waits 1000ms after the last call and then runs: alert("c")
+// alert("c") :تابع معلق 1000 میلیثانیه بعد از آخرین فراخوانی صبر میکند و سپس اجرا میشود
```
-Now a practical example. Let's say, the user types something, and we'd like to send a request to the server when the input is finished.
+حالا یک مثال عملی. بیایید فرض کنیم که کاربر چیزی تایپ میکند و ما میخواهیم یک زمانی که وارد کردن تمام شد یک درخواست به سرور ارسال کنیم.
-There's no point in sending the request for every character typed. Instead we'd like to wait, and then process the whole result.
+دلیلی برای فرستادن درخواست برای هر کاراکتر تایپ شده وجود ندارد. به جای آن ما میخواهیم صبر کنیم و سپس تمام نتیجه را پردازش کنیم.
-In a web-browser, we can setup an event handler -- a function that's called on every change of an input field. Normally, an event handler is called very often, for every typed key. But if we `debounce` it by 1000ms, then it will be only called once, after 1000ms after the last input.
+در یک مرورگر وب، ما میتوانیم یک کنترلکننده رویداد ترتیب دهیم -- تابعی که برای هر تغییر در قسمت ورودی فراخوانی میشود. در حالت عادی، یک کنترلکننده رویداد خیلی فراخوانی میشود، برای هر کلید تایپ شده. اما اگر ما آن را به مدت 1000 میلیثانیه `debounce`(معلق) کنیم، پس از 1000 میلیثانیه بعد از آخرین ورودی، فقط یک بار فراخوانی میشود.
```online
-In this live example, the handler puts the result into a box below, try it:
+در این مثال زنده، کنترلکننده نتیجه را درون جعبه بیرون میگذارد، امتحانش کنید:
[iframe border=1 src="debounce" height=200]
-See? The second input calls the debounced function, so its content is processed after 1000ms from the last input.
+میبینید؟ ورودی دوم، تابع معلق را فراخوانی میکند پس محتوای آن پس از 1000 میلیثانیه بعد از آخرین ورودی پردازش میشود.
```
-So, `debounce` is a great way to process a sequence of events: be it a sequence of key presses, mouse movements or something else.
+پس `debounce` راهی عالی برای پردازش دنبالهای از رویدادها است: چه دنبالهای از فشار دادن کلیدها باشد، چه حرکت مَوس(mouse) یا هر چیز دیگری.
-It waits the given time after the last call, and then runs its function, that can process the result.
+این تابع به اندازه زمان داده شده پس از آخرین فراخوانی صبر میکند و سپس تابع خودش که میتواند نتیجه را پردازش کند را فرا میخواند.
-The task is to implement `debounce` decorator.
+تمرین، پیادهسازی دکوراتور `debounce` است.
-Hint: that's just a few lines if you think about it :)
+راهنمایی: اگر درباره آن فکر کنید، فقط چند خط میشود :)
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
index 8071be9d4..69a725d34 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/_js.view/solution.js
@@ -7,23 +7,23 @@ function throttle(func, ms) {
function wrapper() {
if (isThrottled) {
- // memo last arguments to call after the cooldown
+ // بخاطر سپردن آخرین آرگومانها برای فراخوانی بعد از آرامشدن
savedArgs = arguments;
savedThis = this;
return;
}
- // otherwise go to cooldown state
+ // در غیر این صورت به حالت آرامشدن برو
func.apply(this, arguments);
isThrottled = true;
- // plan to reset isThrottled after the delay
+ // بعد از تأخیر isThrottled زمانبندی برای تنظیم مجدد
setTimeout(function() {
isThrottled = false;
if (savedArgs) {
- // if there were calls, savedThis/savedArgs have the last one
- // recursive call runs the function and sets cooldown again
+ // آخرین آنها را دارند savedThis/savedArgs ،اگر فراخوانیای وجود داشت
+ // فراخوانی بازگشتی تابع را اجرا میکند و حالت آرامشدن را دوباره تنظیم میکند
wrapper.apply(savedThis, savedArgs);
savedArgs = savedThis = null;
}
@@ -31,4 +31,4 @@ function throttle(func, ms) {
}
return wrapper;
-}
\ No newline at end of file
+}
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
index 5b1863a98..3249b7a7e 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/solution.md
@@ -29,10 +29,10 @@ function throttle(func, ms) {
}
```
-A call to `throttle(func, ms)` returns `wrapper`.
+فراخوانی `throttle(func, ms)` تابع `wrapper` را برمیگرداند.
-1. During the first call, the `wrapper` just runs `func` and sets the cooldown state (`isThrottled = true`).
-2. In this state all calls are memorized in `savedArgs/savedThis`. Please note that both the context and the arguments are equally important and should be memorized. We need them simultaneously to reproduce the call.
-3. After `ms` milliseconds pass, `setTimeout` triggers. The cooldown state is removed (`isThrottled = false`) and, if we had ignored calls, `wrapper` is executed with the last memorized arguments and context.
+1. در حین اولین فراخوانی، تابع `wrapper` فقط `func` را اجرا میکند و وضعیت آرامشدن را تنظیم میکند (`isThrottled = true`).
+2. در این حالت، تمام فراخوانیها در `savedArgs/savedThis` ذخیره میشوند. لطفا در نظر داشته باشید که هم زمینه و هم آرگومانها به یک اندازه مهم هستند و باید به یاد سپرده شوند. ما برای اینکه فراخوانی جدید بسازیم به هر دوی آنها نیاز داریم.
+3. بعد از اینکه `ms` میلیثانیه طی شد، `setTimeout` فعال میشود. حالت آرامشدن حذف میشود (`isThrottled = false`) و اگر ما فراخوانی نادیدهگرفتهشدهای داشتیم، `wrapper` همراه با آخرین آرگومانها و زمینه ذخیره شده اجرا میشود.
-The 3rd step runs not `func`, but `wrapper`, because we not only need to execute `func`, but once again enter the cooldown state and setup the timeout to reset it.
+مرحله سوم `wrapper` را اجرا میکند نه `func` را، چون ما نه تنها نیاز داریم که `func` را اجرا کنیم بلکه باید دوباره به حالت آرامشدن برگردیم و زمانبندی را برای تنظیم مجدد آن پیادهسازی کنیم.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
index 6df7af132..931cdc32e 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/04-throttle/task.md
@@ -2,52 +2,52 @@ importance: 5
---
-# Throttle decorator
+# دکوراتور جلوگیرنده
-Create a "throttling" decorator `throttle(f, ms)` -- that returns a wrapper.
+یک دکوراتور «جلوگیرنده» `throttle(f, ms)` بسازید که یک دربرگیرنده را برمیگرداند.
-When it's called multiple times, it passes the call to `f` at maximum once per `ms` milliseconds.
+زمانی که چند بار فراخوانی شد، فقط یک بار به ازای هر `ms` میلیثانیه `f` را فرا میخواند.
-The difference with debounce is that it's completely different decorator:
-- `debounce` runs the function once after the "cooldown" period. Good for processing the final result.
-- `throttle` runs it not more often than given `ms` time. Good for regular updates that shouldn't be very often.
+تفاوت این تابع با معلقکننده این است که کاملا یک دکوراتور متفاوت است:
+- `debounce` تابع را بعد از مدت «آرامشدن» اجرا میکند. برای پردازش نتیجه نهایی خوب است.
+- `throttle` هر بار بعد از گذشت `ms` میلیثانیه تابع را اجرا میکند. برای بروزرسانیهای منظم که نباید زیاد انجام شوند خوب است.
-In other words, `throttle` is like a secretary that accepts phone calls, but bothers the boss (calls the actual `f`) not more often than once per `ms` milliseconds.
+به عبارتی دیگر، `throttle` مانند یک منشی است که تماسهای تلفنی را میپذیرد اما پس از `ms` میلیثانیه فقط یک بار مزاحم رئیس میشود (تابع واقعی `f` را فراخوانی میکند).
-Let's check the real-life application to better understand that requirement and to see where it comes from.
+بیایید کاربردی واقعی را بررسی کنیم تا این نیاز و دلیل وجود آن را بهتر متوجه شویم.
-**For instance, we want to track mouse movements.**
+**برای مثال، ما میخواهیم حرکتهای موس را زیر نظر بگیریم.**
-In a browser we can setup a function to run at every mouse movement and get the pointer location as it moves. During an active mouse usage, this function usually runs very frequently, can be something like 100 times per second (every 10 ms).
-**We'd like to update some information on the web-page when the pointer moves.**
+در مرورگر میتوانیم یک تابع را پیادهسازی کنیم تا با هر حرکت موس اجرا شود و همانطور که موس تکان میخورد موقعیت آن را دریافت کند. در حین استفاده از موس، این تابع معمولا به طور مکرر اجرا میشود و میتواند چیزی مثل 100 بار در ثانیه باشد (هر 10 میلیثانیه).
+**ما میخواهیم زمانی که اشارهگر تکان میخورد اطلاعاتی را در صفحه وب بروزرسانی کنیم.**
-...But updating function `update()` is too heavy to do it on every micro-movement. There is also no sense in updating more often than once per 100ms.
+...اما بروزرسانی تابع `update()` در هر حرکت بسیار کوچک خیلی کار سنگینی است. دلیلی منطقی هم برای برورسانی آن زودتر از هر 100 میلیثانیه وجود ندارد.
-So we'll wrap it into the decorator: use `throttle(update, 100)` as the function to run on each mouse move instead of the original `update()`. The decorator will be called often, but forward the call to `update()` at maximum once per 100ms.
+پس ما آن را درون یک دکوراتور قرار میدهیم: به جای تابع اصلی `update()` از `throttle(update, 100)` به عنوان تابع اجرایی در هر حرکت موس استفاده میکنیم. دکوراتور اکثر مواقع فرا خوانده میشود اما فراخوانی را هر 100 میلیثانیه به `update()` ارسال میکند.
-Visually, it will look like this:
+از لحاظ بصری، اینگونه به نظر خواهد رسید:
-1. For the first mouse movement the decorated variant immediately passes the call to `update`. That's important, the user sees our reaction to their move immediately.
-2. Then as the mouse moves on, until `100ms` nothing happens. The decorated variant ignores calls.
-3. At the end of `100ms` -- one more `update` happens with the last coordinates.
-4. Then, finally, the mouse stops somewhere. The decorated variant waits until `100ms` expire and then runs `update` with last coordinates. So, quite important, the final mouse coordinates are processed.
+1. برای اولین حرکت موس تابع دکور شده بلافاصله فراخوانی را به `update` ارسال میکند. این مهم است که کاربر واکنش ما نسبت به حرکت خود به سرعت ببیند.
+2. سپس همانطور که موس حرکت میکند، تا قبل از `100ms` میلیثانیه چیزی اتفاق نمیافتد. تابع دکوراتور فراخوانیها را نادیده میگیرد.
+3. زمانی که `100ms` تمام میشود، یک بروزرسانی بیشتر `update` با آخرین مختصات اتفاق میافتد.
+4. سپس، بالاخره، موس جایی متوقف میشود. تابع دکور شده صبر میکند تا `100ms` تمام شود و سپس `update` را همراه با آخرین مختصات اجرا میکند. پس خیلی مهم است که آخرین مختصات موس پردازش شود.
-A code example:
+یک مثال از کد:
```js
function f(a) {
console.log(a);
}
-// f1000 passes calls to f at maximum once per 1000 ms
+// منتقل میکند f فراخوانیها را هر 1000 میلیثانیه به f1000 تابع
let f1000 = throttle(f, 1000);
f1000(1); // shows 1
-f1000(2); // (throttling, 1000ms not out yet)
-f1000(3); // (throttling, 1000ms not out yet)
+f1000(2); // (از فراخوانی جلوگیری میکند، هنوز 1000 میلیثانیه نشده است)
+f1000(3); // (از فراخوانی جلوگیری میکند، هنوز 1000 میلیثانیه نشده است)
-// when 1000 ms time out...
-// ...outputs 3, intermediate value 2 was ignored
+// ...زمانی که 1000 میلیثانیه تمام میشود
+// عدد 3 را نشان میدهد، مقدار میانی 2 نادیده گرفته شد...
```
-P.S. Arguments and the context `this` passed to `f1000` should be passed to the original `f`.
+پینوشت: آرگومانها و زمینه `this` که به `f1000` داده میشوند باید به `f` اصلی منتقل شوند.
diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/article.md b/1-js/06-advanced-functions/09-call-apply-decorators/article.md
index c5d785493..07dac421a 100644
--- a/1-js/06-advanced-functions/09-call-apply-decorators/article.md
+++ b/1-js/06-advanced-functions/09-call-apply-decorators/article.md
@@ -1,21 +1,21 @@
-# Decorators and forwarding, call/apply
+# دکوراتورها و ارسال کردن، متدهای call/apply
-JavaScript gives exceptional flexibility when dealing with functions. They can be passed around, used as objects, and now we'll see how to *forward* calls between them and *decorate* them.
+هنگام کار کردن با تابعها، جاوااسکریپت انعطافپذیری بینظیری را ارائه میدهد. تابعها میتوانند رد و بدل شوند، به عنوان شیء استفاده شوند و حالا ما خواهیم دید که چگونه فراخوانیها را بین تابعها *ارسال کنیم* و *رفتار* آنها را *تغییر دهیم*.
-## Transparent caching
+## کش کردن پنهانی
-Let's say we have a function `slow(x)` which is CPU-heavy, but its results are stable. In other words, for the same `x` it always returns the same result.
+فرض کنیم تابع `slow(x)` را داریم که از پردازنده خیلی کار میکشد اما نتیجههای آن همیشه ثابت هستند. به عبارتی دیگر، برای `x` یکسان همیشه نتیجهای یکسان را برمیگردند.
-If the function is called often, we may want to cache (remember) the results to avoid spending extra-time on recalculations.
+اگر تابع زیاد فراخوانی میشود، ممکن است بخواهیم که نتیجهها را کَش کنیم (به یاد بسپاریم) تا از مصرف زمان اضافی برای محاسبات دوباره جلوگیری کنیم.
-But instead of adding that functionality into `slow()` we'll create a wrapper function, that adds caching. As we'll see, there are many benefits of doing so.
+اما به جای اینکه این قابلیت را به `slow(x)` اضافه کنیم یک تابع دربرگیرنده (wrapper) میسازیم که کش کردن را اضافه میکند. همانطور که خواهیم دید، مزایای زیادی از انجام این کار دریافت میکنیم.
-Here's the code, and explanations follow:
+کد اینگونه است و توضیحات به دنبال آن:
```js run
function slow(x) {
- // there can be a heavy CPU-intensive job here
- alert(`Called with ${x}`);
+ // اینجا میتواند یک کاری که پردازنده را زیاد مشغول میکند وجود داشته باشد
+ alert(`با ${x} فراخوانی شد`);
return x;
}
@@ -23,65 +23,65 @@ function cachingDecorator(func) {
let cache = new Map();
return function(x) {
- if (cache.has(x)) { // if there's such key in cache
- return cache.get(x); // read the result from it
+ if (cache.has(x)) { // وجود داشت cache اگر چنین کلیدی در
+ return cache.get(x); // نتیجه را از آن بخوان
}
- let result = func(x); // otherwise call func
+ let result = func(x); // را فراخوانی کن func در غیر این صورت
- cache.set(x, result); // and cache (remember) the result
+ cache.set(x, result); // و نتیجه را کش کن (به خاطر بسپار)
return result;
};
}
slow = cachingDecorator(slow);
-alert( slow(1) ); // slow(1) is cached and the result returned
-alert( "Again: " + slow(1) ); // slow(1) result returned from cache
+alert( slow(1) ); // کش شده و نتیجه آن برگردانده شد slow(1)
+alert( "Again: " + slow(1) ); // از کش برگردانده شد slow(1) نتیجه
-alert( slow(2) ); // slow(2) is cached and the result returned
-alert( "Again: " + slow(2) ); // slow(2) result returned from cache
+alert( slow(2) ); // کش شده و نتیجه آن برگردانده شد slow(2)
+alert( "Again: " + slow(2) ); // از کش برگردانده شد slow(2) نتیجه
```
-In the code above `cachingDecorator` is a *decorator*: a special function that takes another function and alters its behavior.
+در کد بالا `cachingDecorator` یک *دکوراتور* است: تابعی خاص که یک تابع دیگر را دریافت میکند و رفتار آن را تغییر میدهد.
-The idea is that we can call `cachingDecorator` for any function, and it will return the caching wrapper. That's great, because we can have many functions that could use such a feature, and all we need to do is to apply `cachingDecorator` to them.
+ایده این است که ما میتوانیم `cachingDecorator` را برای هر تابعی فراخوانی کنیم و این تابع، دربرگیرنده کشکننده را برمیگرداند. این عالی است چون ما میتوانیم تابعهای زیادی داشته باشیم که از چنین خاصیتی استفاده کنند و تنها کاری که ما باید انجام دهیم، اعمال `cachingDecorator` روی آنها است.
-By separating caching from the main function code we also keep the main code simpler.
+با جدا کردن کش کردن از کد تابع اصلی، ما کد اصلی را هم سادهتر نگه داشتیم.
-The result of `cachingDecorator(func)` is a "wrapper": `function(x)` that "wraps" the call of `func(x)` into caching logic:
+نتیجهی `cachingDecorator(func)` یک «دربرگیرنده» است: تابع `function(x)` که فراخوانی `func(x)` را در منطق کش کردن «میپوشاند»:

-From an outside code, the wrapped `slow` function still does the same. It just got a caching aspect added to its behavior.
+از یک کد بیرونی، تابع `slow` دربر گرفته شده کار یکسانی انجام میدهد. فقط یک جنبه کش کردن به رفتار این تابع اضافه شده است.
-To summarize, there are several benefits of using a separate `cachingDecorator` instead of altering the code of `slow` itself:
+برای خلاصهسازی، چند مزیت در استفاده کردن از یک `cachingDecorator` به صورت جداگانه به جای تغییر کد خود `slow` وجود دارد:
-- The `cachingDecorator` is reusable. We can apply it to another function.
-- The caching logic is separate, it did not increase the complexity of `slow` itself (if there was any).
-- We can combine multiple decorators if needed (other decorators will follow).
+- تابع `cachingDecorator` را میتوان دوباره استفاده کرد. ما میتوانیم آن را روی تابع دیگری هم اعمال کنیم.
+- منطق کش کردن جدا است، این منطق پیچیدگی خود `slow` را افزایش نداد (اگر وجود داشت).
+- اگر نیاز باشد ما میتوانیم چند دکوراتور را ترکیب کنیم (دکوراتورهای دیگر پیروی خواهند کرد).
-## Using "func.call" for the context
+## استفاده از "func.call" برای زمینه
-The caching decorator mentioned above is not suited to work with object methods.
+دکوراتور کش کردن که در بالا گفته شد برای کار با متدهای شیء مناسب نیست.
-For instance, in the code below `worker.slow()` stops working after the decoration:
+برای مثال، در کد پایین `worker.slow()` بعد از دکور کردن کار نمیکند:
```js run
-// we'll make worker.slow caching
+// کش کند worker.slow کاری خواهیم کرد که
let worker = {
someMethod() {
return 1;
},
- slow(x) {
- // scary CPU-heavy task here
- alert("Called with " + x);
+ slow(x) {
+ // کاری که به پردازنده خیلی فشار میآورد را اینجا داریم
+ alert("فراخوانی شده با " + x);
return x * this.someMethod(); // (*)
}
};
-// same code as before
+// کد یکسان قبلی
function cachingDecorator(func) {
let cache = new Map();
return function(x) {
@@ -96,49 +96,49 @@ function cachingDecorator(func) {
};
}
-alert( worker.slow(1) ); // the original method works
+alert( worker.slow(1) ); // متد اصلی کار میکند
-worker.slow = cachingDecorator(worker.slow); // now make it caching
+worker.slow = cachingDecorator(worker.slow); // حالا کاری میکنیم که کش کند
*!*
-alert( worker.slow(2) ); // Whoops! Error: Cannot read property 'someMethod' of undefined
+alert( worker.slow(2) ); // Error: Cannot read property 'someMethod' of undefined !وای یک ارور
*/!*
```
-The error occurs in the line `(*)` that tries to access `this.someMethod` and fails. Can you see why?
+ارور در خط `(*)` اتفاق میافتد، خطی که تلاش میکند به `this.someMethod` دسترسی پیدا کند و شکست میخورد. میتوانید ببینید چرا؟
-The reason is that the wrapper calls the original function as `func(x)` in the line `(**)`. And, when called like that, the function gets `this = undefined`.
+دلیلش این است که دربرگیرنده تابع اصلی را به عنوان `func(x)` در خط `(**)` فراخوانی میکند. و زمانی که اینگونه فرا خواند، تابع `this = undefined` را دریافت میکند.
-We would observe a similar symptom if we tried to run:
+اگر سعی میکردیم که این را اجرا کنیم هم مشکل یکسانی پیش میآمد:
```js
let func = worker.slow;
func(2);
```
-So, the wrapper passes the call to the original method, but without the context `this`. Hence the error.
+پس دربرگیرنده فراخوانی را به متد اصلی میفرستد اما بدون زمینه `this`. به همین دلیل ارور ایجاد میشود.
-Let's fix it.
+بیایید این را درست کنیم.
-There's a special built-in function method [func.call(context, ...args)](mdn:js/Function/call) that allows to call a function explicitly setting `this`.
+یک متد درون ساخت خاص برای تابعها وجود دارد به نام [func.call(context, ...args)](mdn:js/Function/call) که به ما این امکان را میدهد تا به صراحت با تنظیم کردن `this` یک تابع را فرا بخوانیم.
-The syntax is:
+سینتکس اینگونه است:
```js
func.call(context, arg1, arg2, ...)
```
-It runs `func` providing the first argument as `this`, and the next as the arguments.
+این متد با دریافت اولین آرگومان به عنوان `this` و بقیه آنها به عنوان آرگومانهای تابع `func` را اجرا میکند.
-To put it simply, these two calls do almost the same:
+برای اینکه ساده بگوییم، این دو فراخوانی تقریبا کار یکسانی را انجام میدهند:
```js
func(1, 2, 3);
func.call(obj, 1, 2, 3)
```
-They both call `func` with arguments `1`, `2` and `3`. The only difference is that `func.call` also sets `this` to `obj`.
+هر دوی آنها `func` را با آرگومانهای `1`، `2` و `3` فراخوانی میکنند. تنها تفاوت این است که `func.call` مقدار `this` را هم برابر با `obj` قرار میدهد.
-As an example, in the code below we call `sayHi` in the context of different objects: `sayHi.call(user)` runs `sayHi` providing `this=user`, and the next line sets `this=admin`:
+به عنوان مثال، در کد پایین ما `sayHi` را با زمینههای مختلفی از شیءها فراخوانی میکنیم: `sayHi.call(user)` تابع `sayHi` را با تنظیم کردن `this=user` اجرا میکند و خط بعدی `this=admin` را تنظیم میکند:
```js run
function sayHi() {
@@ -148,12 +148,12 @@ function sayHi() {
let user = { name: "John" };
let admin = { name: "Admin" };
-// use call to pass different objects as "this"
+// استفاده کنید "this" برای قرار دادن شیءهای متفاوت به عنوان call از
sayHi.call( user ); // John
sayHi.call( admin ); // Admin
```
-And here we use `call` to call `say` with the given context and phrase:
+و اینجا ما از `call` برای فراخوانی `say` همراه با زمینه و عبارت داده شده استفاده میکنیم:
```js run
@@ -163,11 +163,11 @@ function say(phrase) {
let user = { name: "John" };
-// user becomes this, and "Hello" becomes the first argument
-say.call( user, "Hello" ); // John: Hello
+// قرار میگیرد و "سلام" اولین آرگومان میشود this در user
+say.call( user, "سلام" ); // John: سلام
```
-In our case, we can use `call` in the wrapper to pass the context to the original function:
+در این مورد ما، میتوانیم از `call` درون دربرگیرنده استفاده کنیم تا زمینه را در تابع اصلی تنظیم کنیم:
```js run
let worker = {
@@ -176,7 +176,7 @@ let worker = {
},
slow(x) {
- alert("Called with " + x);
+ alert("فراخوانی شده با " + x);
return x * this.someMethod(); // (*)
}
};
@@ -188,62 +188,62 @@ function cachingDecorator(func) {
return cache.get(x);
}
*!*
- let result = func.call(this, x); // "this" is passed correctly now
+ let result = func.call(this, x); // به درستی قرار داده میشود "this" حالا
*/!*
cache.set(x, result);
return result;
};
}
-worker.slow = cachingDecorator(worker.slow); // now make it caching
+worker.slow = cachingDecorator(worker.slow); // حالا کاری میکنیم که کش کند
-alert( worker.slow(2) ); // works
-alert( worker.slow(2) ); // works, doesn't call the original (cached)
+alert( worker.slow(2) ); // کار میکند
+alert( worker.slow(2) ); // کار میکند، تابع اصلی را فراخوانی نمیکند (کش شده است)
```
-Now everything is fine.
+حالا همه چیز درست است.
-To make it all clear, let's see more deeply how `this` is passed along:
+برای اینکه همه چیز را روشن کنیم، بیایید عمیقتر ببینیم که `this` چگونه تنظیم شده است:
-1. After the decoration `worker.slow` is now the wrapper `function (x) { ... }`.
-2. So when `worker.slow(2)` is executed, the wrapper gets `2` as an argument and `this=worker` (it's the object before dot).
-3. Inside the wrapper, assuming the result is not yet cached, `func.call(this, x)` passes the current `this` (`=worker`) and the current argument (`=2`) to the original method.
+1. بعد از دکور کردن، `worker.slow` همان دربرگیرندهی `function (x) { ... }` است.
+2. پس زمانی که `worker.slow(2)` اجرا میشود، دربرگیرنده `2` را به عنوان آرگومان دریافت میکند و `this=worker` است (همان شیء قبل از نقطه).
+3. درون دربرگیرنده، با فرض اینکه نتیجه هنوز کش نشده است، `func.call(this, x)` مقدار `this` کنونی (=`worker`) و آرگومان کنونی (`=2`) را در متد اصلی تنظیم میکند.
-## Going multi-argument
+## چند آرگومانی شدن
-Now let's make `cachingDecorator` even more universal. Till now it was working only with single-argument functions.
+حالا بیایید `cachingDecorator` را جامعتر کنیم. تا حالا فقط با تابعهایی که یک آرگومان داشتند کار میکرد.
-Now how to cache the multi-argument `worker.slow` method?
+حالا چگونه متد `worker.slow` که چند آرگومان دارد را کش کنیم؟
```js
let worker = {
slow(min, max) {
- return min + max; // scary CPU-hogger is assumed
+ return min + max; // یک کاری که به پردازنده فشار میآورد
}
};
-// should remember same-argument calls
+// باید فراخوانیهایی که آرگومانهای یکسانی دارند را یه خاطر بسپارد
worker.slow = cachingDecorator(worker.slow);
```
-Previously, for a single argument `x` we could just `cache.set(x, result)` to save the result and `cache.get(x)` to retrieve it. But now we need to remember the result for a *combination of arguments* `(min,max)`. The native `Map` takes single value only as the key.
+قبلا، برای یک آرگومان میتوانستیم از `cache.set(x, result)` برای ذخیره نتیجه و `cache.get(x)` برای دریافت آن استفاده کنیم. اما حالا باید نتیجه را برای *ترکیبی از آرگومانها*`(min,max)` ذخیره کنیم. ساختار `Map` فقط یک مقدار را به عنوان کلید دریافت میکند.
-There are many solutions possible:
+چند راهحل احتمالی وجود دارد:
-1. Implement a new (or use a third-party) map-like data structure that is more versatile and allows multi-keys.
-2. Use nested maps: `cache.set(min)` will be a `Map` that stores the pair `(max, result)`. So we can get `result` as `cache.get(min).get(max)`.
-3. Join two values into one. In our particular case we can just use a string `"min,max"` as the `Map` key. For flexibility, we can allow to provide a *hashing function* for the decorator, that knows how to make one value from many.
+1. یک ساختار داده جدید شبیه map پیادهسازی کنیم (یا از شخص ثالث استفاده کنیم) که همهکاره است و چندکلیدی را ممکن میسازد.
+2. از mapهای پیچیده استفاده کنیم: `cache.set(min)` یک `Map` خواهد بود که جفت `(max, result)` را ذخیره میکند. پس ما میتوانیم `result` را به صورت `cache.get(min).get(max)` دریافت کنیم.
+3. دو مقدار را به یک مقدار تبدیل کنیم. در این مورد خاص، میتوانیم از رشته `"min,max"` به عنوان کلید `Map` استفاده کنیم. برای انعطاف پذیری، میتوانیم یک *تابع ترکیبسازی(hashing function)* برای دکوراتور تعیین کنیم که میداند چگونه از چند مقدار یک مقدار بدست آورد.
-For many practical applications, the 3rd variant is good enough, so we'll stick to it.
+برای بسیاری از موارد عملی، نوع سوم به اندازه کافی مناسب است پس ما با همان کار میکنیم.
-Also we need to pass not just `x`, but all arguments in `func.call`. Let's recall that in a `function()` we can get a pseudo-array of its arguments as `arguments`, so `func.call(this, x)` should be replaced with `func.call(this, ...arguments)`.
+همچنین ما باید نه تنها `x` بلکه تمام آرگومانها را در `func.call` قرار دهیم. بیایید یادآوری کنیم که در یک تابع `function()` میتوانیم یک شبهآرایه از آرگومانهای آن را با `arguments` دریافت کنیم پس `func.call(this, ...arguments)` باید جایگزین `func.call(this, x)` شود.
-Here's a more powerful `cachingDecorator`:
+اینجا یک `cachingDecorator` قدرتمندتر داریم:
```js run
let worker = {
slow(min, max) {
- alert(`Called with ${min},${max}`);
+ alert(`فراخوانی شده با ${min},${max}`);
return min + max;
}
};
@@ -273,50 +273,50 @@ function hash(args) {
worker.slow = cachingDecorator(worker.slow, hash);
-alert( worker.slow(3, 5) ); // works
-alert( "Again " + worker.slow(3, 5) ); // same (cached)
+alert( worker.slow(3, 5) ); // کار میکند
+alert( "Again " + worker.slow(3, 5) ); // یکسان است (کش شده)
```
-Now it works with any number of arguments (though the hash function would also need to be adjusted to allow any number of arguments. An interesting way to handle this will be covered below).
+حالا این تابع با هر تعداد آرگومان کار میکند (گرچه تابع ترکیبسازی هم باید جوری تنظیم شود که هر تعداد آرگومان را قبول کند. یک راه جالب برای کنترل این موضوع پایینتر پوشش داده شده است).
-There are two changes:
+دو تفاوت وجود دارد:
-- In the line `(*)` it calls `hash` to create a single key from `arguments`. Here we use a simple "joining" function that turns arguments `(3, 5)` into the key `"3,5"`. More complex cases may require other hashing functions.
-- Then `(**)` uses `func.call(this, ...arguments)` to pass both the context and all arguments the wrapper got (not just the first one) to the original function.
+- در خط `(*)` این تابع، `hash` را فراخوانی میکند تا یک کلید را از `arguments` بسازد. اینجا ما از تابع ساده «پیوند دادن» استفاده کردیم که آرگومانهای `(3, 5)` را به کلید `"3,5"` تبدیل میکند. موارد پیچیدهتر ممکن است تابعهای ترکیبسازی دیگری را نیاز داشته باشند.
+- سپس خط `(**)` برای اینکه زمینه و تمام آرگومانهایی که دربرگیرنده دریافت کرد (نه فقط اولی) را در تابع اصلی قرار دهد از `func.call(this, ...arguments)` استفاده میکند.
-## func.apply
+## متد func.apply
-Instead of `func.call(this, ...arguments)` we could use `func.apply(this, arguments)`.
+میتوانستیم به جای `func.call(this, ...arguments)` از `func.apply(this, arguments)` استفاده کنیم.
-The syntax of built-in method [func.apply](mdn:js/Function/apply) is:
+سینتکس متد درونساخت [func.apply](mdn:js/Function/apply) اینگونه است:
```js
func.apply(context, args)
```
-It runs the `func` setting `this=context` and using an array-like object `args` as the list of arguments.
+این متد با تنظیم کردن `this=context` و استفاده از شیء `args` به عنوان لیستی از آرگومانها، تابع `func` را فراخوانی میکند.
-The only syntax difference between `call` and `apply` is that `call` expects a list of arguments, while `apply` takes an array-like object with them.
+تنها تفاوت بین `call` و `apply` این است که `call` لیستی از آرگومانها را قبول میکند در حالی که `apply` یک شیء شبهآرایه که شامل آرگومانها است را قبول میکند.
-So these two calls are almost equivalent:
+پس این دو فراخوانی تقریبا یکی هستند:
```js
func.call(context, ...args);
func.apply(context, args);
```
-They perform the same call of `func` with given context and arguments.
+آنها فراخوانی یکسانی از `func` همراه با زمینه و آرگومانهای داده شده را انجام میدهند.
-There's only a subtle difference regarding `args`:
+فقط یک تفاوت جزئی در مورد `args` وجود دارد:
-- The spread syntax `...` allows to pass *iterable* `args` as the list to `call`.
-- The `apply` accepts only *array-like* `args`.
+- سینتکس اسپرد `...` به ما اجازه میدهد تا `args` *حلقهپذیر* را به عنوان لیست در `call` قرار دهیم.
+- متد `apply` فقط `args` *شبهآرایه* را قبول میکند.
-...And for objects that are both iterable and array-like, such as a real array, we can use any of them, but `apply` will probably be faster, because most JavaScript engines internally optimize it better.
+...و برای شیءهایی که هم حلقهپذیر و هم شبهآرایه هستند، مانند آرایه واقعی، ما میتوانیم هر یک از آنها را استفاده کنیم اما احتمالا `apply` سریعتر باشد چون بیشتر موتورهای جاوااسکریپت آن را از دورن بهتر بهینه کردهاند.
-Passing all arguments along with the context to another function is called *call forwarding*.
+قرار دادن تمام آرگومانها در کنار زمینه در تابعی دیگر را *ارسال کردن فراخوانی(call forwarding)* میگویند.
-That's the simplest form of it:
+این سادهترین شکل از آن است:
```js
let wrapper = function() {
@@ -324,11 +324,11 @@ let wrapper = function() {
};
```
-When an external code calls such `wrapper`, it is indistinguishable from the call of the original function `func`.
+زمانی که یک کد بیرونی این `wrapper` را فراخوانی کند، نمیتوان آن را از فراخوانی تابع اصلی `func` تشخیص داد.
-## Borrowing a method [#method-borrowing]
+## قرض گرفتن یک متد [#method-borrowing]
-Now let's make one more minor improvement in the hashing function:
+حالا بیایید یک پیشرفت جزئی دیگر در تابع ترکیبسازی ایجاد کنیم:
```js
function hash(args) {
@@ -336,9 +336,9 @@ function hash(args) {
}
```
-As of now, it works only on two arguments. It would be better if it could glue any number of `args`.
+اکنون، این تابع فقط روی دو آرگومان کار میکند. اگر این تابع بتواند هر تعداد `args` را به هم بچسباند بهتر میشد.
-The natural solution would be to use [arr.join](mdn:js/Array/join) method:
+راهحل طبیعی استفاده از متد [arr.join](mdn:js/Array/join) است:
```js
function hash(args) {
@@ -346,9 +346,9 @@ function hash(args) {
}
```
-...Unfortunately, that won't work. Because we are calling `hash(arguments)`, and `arguments` object is both iterable and array-like, but not a real array.
+...متاسفانه این روش کار نخواهد کرد. چون ما در حال فراخوانی `hash(arguments)` هستیم و شیء `arguments` هم حلقهپذیر است و هم شبهآرایه اما یک آرایه واقعی نیست.
-So calling `join` on it would fail, as we can see below:
+پس همانطور که در کد پایین میبینیم، فراخوانی `join` بر روی آن با شکست مواجه میشود:
```js run
function hash() {
@@ -360,7 +360,7 @@ function hash() {
hash(1, 2);
```
-Still, there's an easy way to use array join:
+اما هنوز یک راه آسان برای استفاده از پیوند دادن آرایه وجود دارد:
```js run
function hash() {
@@ -372,48 +372,48 @@ function hash() {
hash(1, 2);
```
-The trick is called *method borrowing*.
+این ترفند *قرضگیری متد (method borrowing)* نام دارد.
-We take (borrow) a join method from a regular array (`[].join`) and use `[].join.call` to run it in the context of `arguments`.
+ما متد پیوند دادن را از یک آرایه معمولی (قرض) میگیریم (`[].join`) و برای اجرای آن با زمینه `arguments` از `[].join.call` استفاده میکنیم.
-Why does it work?
+این چرا کار میکند؟
-That's because the internal algorithm of the native method `arr.join(glue)` is very simple.
+به دلیل اینکه الگوریتم داخلی متد نیتیو (native method) `arr.join(glue)` بسیار ساده است.
-Taken from the specification almost "as-is":
+این مراحل تقریبا «بدون تغییر» از مشخصات زبان برداشته شده است:
-1. Let `glue` be the first argument or, if no arguments, then a comma `","`.
-2. Let `result` be an empty string.
-3. Append `this[0]` to `result`.
-4. Append `glue` and `this[1]`.
-5. Append `glue` and `this[2]`.
-6. ...Do so until `this.length` items are glued.
-7. Return `result`.
+1. فرض کنیم که `glue` آرگومان اول باشد یا اگر آرگومانی وجود نداشت، پس یک کاما `","`.
+2. فرض کنیم `result` یک رشته خالی باشد.
+3. `this[0]` را به `result` اضافه کنید.
+4. `glue` و `this[1]` را اضافه کنید.
+5. `glue` و `this[2]` را اضافه کنید.
+6. ...تا زمانی که تعداد `this.length` المان به هم چسبیدند ادامه دهید.
+9. `result` را برگردانید.
-So, technically it takes `this` and joins `this[0]`, `this[1]` ...etc together. It's intentionally written in a way that allows any array-like `this` (not a coincidence, many methods follow this practice). That's why it also works with `this=arguments`.
+پس از لحاظ فنی این تابع `this` را دریافت میکند و `this[0]`، `this[1]` و بقیه را به هم پیوند میزند. این متد از قصد طوری نوشته شده است که هر `this` شبهآرایه را قبول کند (این اتفاقی نیست، بسیاری از متدها از این موضوع پیروی میکنند). به همین دلیل است که با `this=arguments` هم کار میکند.
-## Decorators and function properties
+## دکوراتورها و ویژگیهای تابع
-It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one needs to be careful if one uses them.
+به طور کلی اینکه یک تابع یا متد را با تابعی دکور شده جایگزین کنیم مشکلی ایجاد نمیکند به جز در موردی کوچک. اگر تابع اصلی ویژگیهایی درون خود داشته باشد، مثلا `func.calledCount` یا هر چیزی، سپس تابع دکور شده آنها را فراهم نمیکند. چون یک دربرگیرنده است. پس اگر کسی از دکوراتورها استفاده کرد باید حواسش به این موضوع باشد.
-E.g. in the example above if `slow` function had any properties on it, then `cachingDecorator(slow)` is a wrapper without them.
+برای نمونه، در مثال بالا اگر تابع `slow` ویژگیای درون خودش داشت، سپس `cachingDecorator(slow)` یک دربرگیرنده خواهد بود که آن ویژگی را ندارد.
-Some decorators may provide their own properties. E.g. a decorator may count how many times a function was invoked and how much time it took, and expose this information via wrapper properties.
+بعضی از دکوراتورها ممکن است ویژگیهای خودشان را داشته باشند. مثلا یک دکوراتور میتواند تعداد دفعاتی که یک تابع فراخوانی شده و اجرای آن چقدر زمان برده است را محاسبه کند و از طریق ویژگیهای دربرگیرنده این اطلاعات را در اختیار بگذارد.
-There exists a way to create decorators that keep access to function properties, but this requires using a special `Proxy` object to wrap a function. We'll discuss it later in the article