diff --git a/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/solution.md b/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/solution.md index ebd2f44e9..da3c37523 100644 --- a/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/solution.md +++ b/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/solution.md @@ -9,5 +9,5 @@ function f() { alert("Hello!"); } -f.defer(1000); // shows "Hello!" after 1 sec +f.defer(1000); // را نشان می‌دهد "Hello!" بعد از 1 ثانیه ``` diff --git a/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/task.md b/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/task.md index d3b3a51c2..7310d615b 100644 --- a/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/task.md +++ b/1-js/08-prototypes/03-native-prototypes/1-defer-to-prototype/task.md @@ -2,16 +2,16 @@ importance: 5 --- -# Add method "f.defer(ms)" to functions +# متد "f.defer(ms)" را به تابع‌ها اضافه کنید -Add to the prototype of all functions the method `defer(ms)`, that runs the function after `ms` milliseconds. +متد `defer(ms)` را به پروتوتایپ تمام تابع‌ها اضافه کنید که تابع را بعد از `ms` میلی‌ثانیه اجرا می‌کند. -After you do it, such code should work: +بعد از اینکه آن را انجام دادید، چنین کدی باید کار کند: ```js function f() { alert("Hello!"); } -f.defer(1000); // shows "Hello!" after 1 second +f.defer(1000); // را نشان می‌دهد "Hello!" بعد از 1 ثانیه ``` diff --git a/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md index 99c358c9b..02057bd13 100644 --- a/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md +++ b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/solution.md @@ -8,17 +8,17 @@ Function.prototype.defer = function(ms) { } }; -// check it +// آن را بررسی کنید function f(a, b) { alert( a + b ); } -f.defer(1000)(1, 2); // shows 3 after 1 sec +f.defer(1000)(1, 2); // بعد از 1 ثانیه 3 را نمایش می‌دهد ``` -Please note: we use `this` in `f.apply` to make our decoration work for object methods. +لطفا توجه کنید: ما در `f.apply` از `this` استفاده کردیم تا کاری کنیم که دکور کردن برای متدهای شیء هم کار کند. -So if the wrapper function is called as an object method, then `this` is passed to the original method `f`. +پس اگر تابع دربرگیرنده به عنوان متد شیء فراخوانی شود، سپس `this` به متد اصلی `f` پاس داده می‌شود. ```js run Function.prototype.defer = function(ms) { diff --git a/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/task.md b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/task.md index 4d3823bb8..8c0ca3da2 100644 --- a/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/task.md +++ b/1-js/08-prototypes/03-native-prototypes/2-defer-to-prototype-extended/task.md @@ -2,18 +2,18 @@ importance: 4 --- -# Add the decorating "defer()" to functions +# دکوراتور "defer()" را به تابع‌ها اضافه کنید -Add to the prototype of all functions the method `defer(ms)`, that returns a wrapper, delaying the call by `ms` milliseconds. +متد `defer(ms)` را به پروتوتایپ تمام تابع‌ها اضافه کنید که یک دربرگیرنده را برمی‌گرداند و فراخوانی را به اندازه `ms` میلی‌ثانیه به تاخیر می‌اندازد. -Here's an example of how it should work: +این کد نمونه‌ای چگونگی کار کردن آن است: ```js function f(a, b) { alert( a + b ); } -f.defer(1000)(1, 2); // shows 3 after 1 second +f.defer(1000)(1, 2); // بعد از 1 ثانیه 3 را نمایش می‌دهد ``` -Please note that the arguments should be passed to the original function. +لطفا در نظر داشته باشید که آرگومان‌ها باید به تابع اصلی پاس داده شوند. diff --git a/1-js/08-prototypes/03-native-prototypes/article.md b/1-js/08-prototypes/03-native-prototypes/article.md index 6cf7aebb4..95956061b 100644 --- a/1-js/08-prototypes/03-native-prototypes/article.md +++ b/1-js/08-prototypes/03-native-prototypes/article.md @@ -1,33 +1,33 @@ -# Native prototypes +# پروتوتایپ‌های نیتیو (Native prototypes) -The `"prototype"` property is widely used by the core of JavaScript itself. All built-in constructor functions use it. +ویژگی `"prototype"` به طور گسترده توسط هسته خود جاوااسکریپت استفاده می‌شود. تمام تابع‌های سازنده درون‌ساخت از آن استفاده می‌کنند. -First we'll see at the details, and then how to use it for adding new capabilities to built-in objects. +در ابتدا به جزئیات می‌پردازیم و سپس چگونگی استفاده کردن از آن برای اضافه کردن قابلیت‌های جدید به شیءهای درون‌ساخت را بررسی می‌کنیم. -## Object.prototype +## ویژگی Object.prototype -Let's say we output an empty object: +فرض کنیم ما یک شیء خالی را خروجی می‌گیریم: ```js run let obj = {}; alert( obj ); // "[object Object]" ? ``` -Where's the code that generates the string `"[object Object]"`? That's a built-in `toString` method, but where is it? The `obj` is empty! +کدی که رشته `"[object Object]"` را ایجاد می‌کند کجاست؟ این کد یک متد `toString` درون‌ساخت است اما کجاست؟ `obj` خالی است! -...But the short notation `obj = {}` is the same as `obj = new Object()`, where `Object` is a built-in object constructor function, with its own `prototype` referencing a huge object with `toString` and other methods. +...اما نماد کوتاه `obj = {}` با `obj = new Object()` یکسان است، که `Object` یک تابع سازنده درون‌ساخت شیء است، که دارای `prototype` است که به یک شیء بسیار بزرگ حاوی `toString` و متدهای دیگر رجوع می‌کند. -Here's what's going on: +اینجا می‌بینیم که چه اتفاقی در حال رخ دادن است: ![](object-prototype.svg) -When `new Object()` is called (or a literal object `{...}` is created), the `[[Prototype]]` of it is set to `Object.prototype` according to the rule that we discussed in the previous chapter: +زمانی که `new Object()` فراخوانی شود (یا یک شیء لیترال `{...}` ساخته می‌شود)، با توجه به قانونی که ما در فصل قبلی درباره آن صحبت کردیم، `[[Prototype]]` آن در `Object.prototype` قرار داده می‌شود: ![](object-prototype-1.svg) -So then when `obj.toString()` is called the method is taken from `Object.prototype`. +سپس زمانی که `obj.toString()` فراخوانی می‌شود، این متد از `Object.prototype` گرفته می‌شود. -We can check it like this: +می‌توانیم آن را به این صورت بررسی کنیم: ```js run let obj = {}; @@ -38,80 +38,80 @@ alert(obj.toString === obj.__proto__.toString); //true alert(obj.toString === Object.prototype.toString); //true ``` -Please note that there is no more `[[Prototype]]` in the chain above `Object.prototype`: +لطفا در نظر داشته باشید که `[[Prototype]]` دیگری در زنجیره بالای `Object.prototype` وجود ندارد: ```js run alert(Object.prototype.__proto__); // null ``` -## Other built-in prototypes +## دیگر پروتوتایپ‌های درون‌ساخت -Other built-in objects such as `Array`, `Date`, `Function` and others also keep methods in prototypes. +شیءهای دیگر درون‌ساخت مانند `Array`، `Date`، `Function` و بقیه هم متدهایی درون پروتوتایپ‌ها ذخیره می‌کنند. -For instance, when we create an array `[1, 2, 3]`, the default `new Array()` constructor is used internally. So `Array.prototype` becomes its prototype and provides methods. That's very memory-efficient. +برای مثال، زمانی که ما آرایه `[1, 2, 3]` را می‌سازیم، سازنده `new Array()` به صورت درونی استفاده می‌شود. پس `Array.prototype` پروتوتایپ آن می‌شود و متدها را فراهم می‌کند. این کار برای حافظه خیلی کارآمد است. -By specification, all of the built-in prototypes have `Object.prototype` on the top. That's why some people say that "everything inherits from objects". +با توجه به خصوصیات زبان، تمام پروتوتایپ‌ها، `Object.prototype` را بالای خود دارند. به همین دلیل است که بعضی افراد می‌گویند «همه چیز از شیءها ارث‌بری می‌کنند». -Here's the overall picture (for 3 built-ins to fit): +اینجا یک تصویر کلی داریم (برای 3 سازنده درون‌ساخت تا جا شود): ![](native-prototypes-classes.svg) -Let's check the prototypes manually: +بیایید به صورت دستی پروتوتایپ‌ها را بررسی کنیم: ```js run let arr = [1, 2, 3]; -// it inherits from Array.prototype? +// ارث‌بری می‌کند؟ Array.prototype آیا از alert( arr.__proto__ === Array.prototype ); // true -// then from Object.prototype? +// چطور؟ Object.prototype سپس از alert( arr.__proto__.__proto__ === Object.prototype ); // true -// and null on the top. +// قرار دارد null و در بالا alert( arr.__proto__.__proto__.__proto__ ); // null ``` -Some methods in prototypes may overlap, for instance, `Array.prototype` has its own `toString` that lists comma-delimited elements: +بعضی از متدها در پروتوتایپ‌ها ممکن است با هم تطابق داشته باشند، برای مثال `Array.prototype` متد `toString` خودش را دارد که المان‌ها را به صورت جداشده توسط کاما لیست می‌کند: ```js run let arr = [1, 2, 3] -alert(arr); // 1,2,3 <-- the result of Array.prototype.toString +alert(arr); // 1,2,3 <-- Array.prototype.toString نتیجه‌ی ``` -As we've seen before, `Object.prototype` has `toString` as well, but `Array.prototype` is closer in the chain, so the array variant is used. +همانطور که قبلا دیدیم، `Object.prototype` هم متد `toString` را دارد اما `Array.prototype` در زنجیره نزدیک‌تر است پس نوع آرایه آن استفاده می‌شود. ![](native-prototypes-array-tostring.svg) -In-browser tools like Chrome developer console also show inheritance (`console.dir` may need to be used for built-in objects): +ابزارهای درون مرورگر مانند کنسول توسعه‌دهنده کروم هم ارث‌بری را نشان می‌دهند (ممکن است برای شیءهای درون‌ساخت نیاز باشد که `console.dir` استفاده شود): ![](console_dir_array.png) -Other built-in objects also work the same way. Even functions -- they are objects of a built-in `Function` constructor, and their methods (`call`/`apply` and others) are taken from `Function.prototype`. Functions have their own `toString` too. +بقیه شیءهای درون‌ساخت هم این چنین کار می‌کنند. حتی تابع‌ها -- آن‌ها شیءهایی از سازنده `Function` هستند و متدهای آن‌ها (`call`/`apply` و بقیه) از `Function.prototype` گرفته می‌شوند. تابع‌ها `toString` خودشان را هم دارند. ```js run function f() {} alert(f.__proto__ == Function.prototype); // true -alert(f.__proto__.__proto__ == Object.prototype); // true, inherit from objects +alert(f.__proto__.__proto__ == Object.prototype); // true ،ارث‌بری از شیءها ``` -## Primitives +## مقدارهای اصلی -The most intricate thing happens with strings, numbers and booleans. +پیچیده‌ترین چیزی که با رشته‌ها، عددها و بولین‌ها اتفاق می‌افتد. -As we remember, they are not objects. But if we try to access their properties, temporary wrapper objects are created using built-in constructors `String`, `Number` and `Boolean`. They provide the methods and disappear. +همانطور که به یاد داریم، آن‌ها شیء نیستند. اما اگر سعی کنیم که به ویژگی‌های آن‌ها دسترسی پیدا کنیم، شیءهای دربرگیرنده موقتی با استفاده از سازنده‌های درون‌ساخت `String`، `Number` و `Boolean` ساخته می‌شوند. آن‌ها متدها را فراهم می‌کنند و سپس ناپدید می‌شوند. -These objects are created invisibly to us and most engines optimize them out, but the specification describes it exactly this way. Methods of these objects also reside in prototypes, available as `String.prototype`, `Number.prototype` and `Boolean.prototype`. +این شیءها به صورت پنهانی ایجاد می‌شوند و بیشتر موتورها آن‌ها را بهینه می‌کنند اما خصوصیات زبان دقیقا به همین صورت آن‌ها را توصیف می‌کند. متدهای این شیءها هم درون پروتوتایپ‌ها قرار دارند و به صورت `String.prototype`، `Number.prototype` و `Boolean.prototype` در دسترس هستند. -```warn header="Values `null` and `undefined` have no object wrappers" -Special values `null` and `undefined` stand apart. They have no object wrappers, so methods and properties are not available for them. And there are no corresponding prototypes either. +```warn header="مقدارهای `null` و `undefined` دارای دربرگیرنده شیء نیستند" +مقدارهای خاص `null` و `undefined` استثنا هستند. آن‌ها دربرگیرنده شیء ندارند پس متدها و ویژگی‌هایی هم برای آن‌ها موجود نیست. و پروتوتایپ‌های متناظر هم وجود ندارد. ``` -## Changing native prototypes [#native-prototype-change] +## تغییر پروتوتایپ‌های نیتیو [#native-prototype-change] -Native prototypes can be modified. For instance, if we add a method to `String.prototype`, it becomes available to all strings: +پروتوتایپ‌های نیتیو (Native prototypes) می‌توانند تغییر کنند. برای مثال، اگر ما متدی را به `String.prototype` اضافه کنیم، این متد برای تمام رشته‌ها در دسترس خواهد بود: ```js run String.prototype.show = function() { @@ -121,32 +121,32 @@ String.prototype.show = function() { "BOOM!".show(); // BOOM! ``` -During the process of development, we may have ideas for new built-in methods we'd like to have, and we may be tempted to add them to native prototypes. But that is generally a bad idea. +در حین فرایند توسعه، ممکن است ایده‌هایی برای متدهای درون‌ساخت جدیدی به ذهن‌مان برسد که بخواهیم آن‌ها را داشته باشیم و ممکن است مشتاق باشیم که آن‌ها را به پروتوتایپ‌های نیتیو اضافه کنیم. اما به طور کلی این کار بدی است. ```warn -Prototypes are global, so it's easy to get a conflict. If two libraries add a method `String.prototype.show`, then one of them will be overwriting the method of the other. +پروتوتایپ‌ها گلوبال هستند، پس دریافت تناقض آسان است. اگر دو کتابخانه متد `String.prototype.show` را اضافه کنند، یکی از آن‌ها ممکن است متد دیگری را بازنویسی کند. -So, generally, modifying a native prototype is considered a bad idea. +پس به طور کلی، تغییر یک پروتوتایپ نیتیو کار بدی محسوب می‌شود. ``` -**In modern programming, there is only one case where modifying native prototypes is approved. That's polyfilling.** +**در برنامه‌نویسی مدرن، فقط یک مورد است که تغییر دادن پروتوتایپ‌های نیتیو قابل قبول است. آن هم پلیفیل‌سازی است.** -Polyfilling is a term for making a substitute for a method that exists in the JavaScript specification, but is not yet supported by a particular JavaScript engine. +پلیفیل‌سازی (polyfilling) عبارتی برای ایجاد یک جایگزین برای متدی است که در خصوصیات جاوااسکریپت وجود دارد اما هنوز توسط موتور جاوااسکریپت خاصی پشتیبانی نمی‌شود. -We may then implement it manually and populate the built-in prototype with it. +سپس می‌توانیم آن را به صورت دستی پیاده‌سازی و به پروتوتایپ درون‌ساخت اضافه کنیم. -For instance: +برای مثال: ```js run -if (!String.prototype.repeat) { // if there's no such method - // add it to the prototype +if (!String.prototype.repeat) { // اگر چنین متدی وجود نداشته باشد + // آن را به پروتوتایپ اضافه کن String.prototype.repeat = function(n) { - // repeat the string n times + // بار تکرار کن n رشته را - // actually, the code should be a little bit more complex than that - // (the full algorithm is in the specification) - // but even an imperfect polyfill is often considered good enough + // در واقع کد باید نسبت به این کمی بیشتر پیچیده باشد + // (الگوریتم کامل درون خصوصیات زبان موجود است) + // اما حتی یک پلیفیل ناکامل هم اغلب اوقات کافی است return new Array(n + 1).join(this); }; } @@ -155,17 +155,17 @@ alert( "La".repeat(3) ); // LaLaLa ``` -## Borrowing from prototypes +## قرض گرفتن از پروتوتایپ‌ها -In the chapter we talked about method borrowing. +در فصل ما درباره قرض گرفتن متد صحبت کردیم. -That's when we take a method from one object and copy it into another. +این زمانی است که ما متدی را از یک شیء دریافت می‌کنیم و آن را درون شیء دیگری کپی می‌کنیم. -Some methods of native prototypes are often borrowed. +بعضی از متدهای پروتوتایپ‌های نیتیو اغلب اوقات قرض گرفته می‌شوند. -For instance, if we're making an array-like object, we may want to copy some `Array` methods to it. +برای مثال، اگر ما در حال ساخت یک شیء آرایه مانند باشیم، ممکن است بخواهیم بعضی از متدهای `Array` را درون آن کپی کنیم. -E.g. +برای مثال: ```js run let obj = { @@ -181,18 +181,19 @@ obj.join = Array.prototype.join; alert( obj.join(',') ); // Hello,world! ``` -It works because the internal algorithm of the built-in `join` method only cares about the correct indexes and the `length` property. It doesn't check if the object is indeed an array. Many built-in methods are like that. +این کد کار می‌کند چون الگوریتم داخلی متد درون‌ساخت `join` فقط به ایندکس‌های درست و ویژگی `length` اهمیت می‌دهد. این متد بررسی نمی‌کند که شیء واقعا یک آرایه باشد. بسیاری از متدهای درون‌ساخت همینگونه هستند. -Another possibility is to inherit by setting `obj.__proto__` to `Array.prototype`, so all `Array` methods are automatically available in `obj`. +احتمال دیگر هم ارث‌بری است که از طریق برابر قرار دادن `obj.__proto__` با `Array.prototype` انجام می‌شود، پس تمام متدهای `Array` به صورت خودکار درون `obj` قابل دسترسی خواهند بود. -But that's impossible if `obj` already inherits from another object. Remember, we only can inherit from one object at a time. +اما اگر `obj` از قبل از شیء دیگری ارث‌بری کند این کار ناممکن می‌شود. به یاد داشته باشید، ما به طور همزمان فقط می‌توانیم از یک شیء ارث‌بری کنیم. -Borrowing methods is flexible, it allows to mix functionalities from different objects if needed. +قرض گرفتن متدها قابل انعطاف است، این روش اجازه می‌دهد که در صورت نیاز عملیات‌هایی از شیءهای مختلف را با هم ترکیب کنیم. -## Summary +## خلاصه -- All built-in objects follow the same pattern: - - The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype`, etc.) +- تمام شیءهای درون‌ساخت الگویی یکسان را دنبال می‌کنند: + - متدها درون پروتوتایپ ذخیره شده‌اند (`Array.prototype`، `Object.prototype`، `Date.prototype` و غیره.) - The object itself stores only the data (array items, object properties, the date) -- Primitives also store methods in prototypes of wrapper objects: `Number.prototype`, `String.prototype` and `Boolean.prototype`. Only `undefined` and `null` do not have wrapper objects -- Built-in prototypes can be modified or populated with new methods. But it's not recommended to change them. The only allowable case is probably when we add-in a new standard, but it's not yet supported by the JavaScript engine + - خود شیء فقط داده را ذخیره می‌کند (المان‌های آرایه، ویژگی‌های شیء، تاریخ) +- مقدارهای اصلی هم متدها را درون پروتوتایپ‌های شیءهای دربرگیرنده ذخیره می‌کنند : `Number.prototype`، `String.prototype` و `Boolean.prototype`. فقط `undefined` و `null` شیءهای دربرگیرنده ندارند. +- پروتوتایپ‌های درون‌ساخت می‌توانند تغییر کنند یا با متدهای جدید پر شوند. اما پیشنهاد نمی‌شود که آن‌ها را تغییر دهید. تنها موردی که مجاز است احتمالا زمانی است که ما می‌خواهیم یک استاندارد جدید را اضافه کنیم اما هنوز توسط موتور جاوااسکریپت پشتیبانی نشده است.