Skip to content

Extending built-in classes #184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 29, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 25 additions & 25 deletions 1-js/09-classes/05-extend-natives/article.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

# Extending built-in classes
# تعمیم دادن کلاس‌های درون‌ساخت

Built-in classes like Array, Map and others are extendable also.
کلاس‌های درون‌ساخت مانند Array، Map و بقیه هم قابل تعمیم هستند.

For instance, here `PowerArray` inherits from the native `Array`:
برای مثال، اینجا `PowerArray` از `Array` نیتیو ارث‌بری می‌کند:

```js run
// add one more method to it (can do more)
// اضافه کردن یک متد دیگر به آن (می‌توانیم بیشتر هم اضافه کنیم)
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
Expand All @@ -21,20 +21,20 @@ alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false
```

Please note a very interesting thing. Built-in methods like `filter`, `map` and others -- return new objects of exactly the inherited type `PowerArray`. Their internal implementation uses the object's `constructor` property for that.
لطفا به یک موضوع جالب توجه کنید. متدهای درون‌ساخت مانند `filter`، `map` و بقیه -- شیءهای جدیدی که دقیقا از `PowerArray` به ارث برده شده ساخته شده‌اند را برمی‌گردانند. پیاده‌سازی درونی آن‌ها از ویژگی `constructor` شیء برای این کار استفاده می‌کند.

In the example above,
در مثال بالا،
```js
arr.constructor === PowerArray
```

When `arr.filter()` is called, it internally creates the new array of results using exactly `arr.constructor`, not basic `Array`. That's actually very cool, because we can keep using `PowerArray` methods further on the result.
زمانی که `arr.filter()` فراخوانی می‌شود، از درون، آرایه‌ای جدید از نتیجه‌ها را با استفاده از `arr.constructor` ایجاد می‌کند نه `Array` پایه‌ای.

Even more, we can customize that behavior.
حتی فراتر از آن، می‌توانیم این عملکرد را شخصی‌سازی کنیم.

We can add a special static getter `Symbol.species` to the class. If it exists, it should return the constructor that JavaScript will use internally to create new entities in `map`, `filter` and so on.
می‌توانیم یک getter استاتیک `Symbol.species` خاص را به کلاس اضافه کنیم. اگر این متد وجود داشته باشد، باید تابع سازنده‌ای که جاوااسکریپت از درون برای ایجاد المان‌های جدید درون `map`، `filter` و بقیه استفاده می‌کند را برگرداند.

If we'd like built-in methods like `map` or `filter` to return regular arrays, we can return `Array` in `Symbol.species`, like here:
اگر بخواهیم متدهای درون‌ساخت مانند `map` یا `filter` آرایه‌های معمولی برگردانند، می‌توانیم در `Symbol.species` کلاس `Array` را برگردانیم، مثل اینجا:

```js run
class PowerArray extends Array {
Expand All @@ -43,7 +43,7 @@ class PowerArray extends Array {
}

*!*
// built-in methods will use this as the constructor
// متدهای درون‌ساخت از این به عنوان تابع سازنده استفاده می‌کنند
static get [Symbol.species]() {
return Array;
}
Expand All @@ -53,37 +53,37 @@ class PowerArray extends Array {
let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

// filter creates new array using arr.constructor[Symbol.species] as constructor
// به عنوان سازنده، آرایه‌ای جدید تشکیل می‌دهد arr.constructor[Symbol.species] با استفاده از filter
let filteredArr = arr.filter(item => item >= 10);

*!*
// filteredArr is not PowerArray, but Array
// است Array نیست بلکه PowerArray یک filteredArr
*/!*
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
```

As you can see, now `.filter` returns `Array`. So the extended functionality is not passed any further.
همانطور که می‌بینید، حالا `.filter` کلاس `Array` را برمی‌گرداند. پس عملکرد تعمیم داده شده دیگر پاس داده نمی‌شود.

```smart header="Other collections work similarly"
Other collections, such as `Map` and `Set`, work alike. They also use `Symbol.species`.
```smart header="مجموعه‌های دیگر هم به طور مشابه عمل می‌کنند"
مجموعه‌های دیگر، مثال `Map` و `Set`، همینطور کار می‌کنند. آن‌ها هم از `Symbol.species` استفاده می‌کنند.
```

## No static inheritance in built-ins
## ارث‌بری ایستا در درون‌ساخت‌ها وجود ندارد

Built-in objects have their own static methods, for instance `Object.keys`, `Array.isArray` etc.
شیءهای درون‌ساخت متدهای ایستا خود را دارند، برای مثال `Object.keys`، `Array.isArray` و غیره.

As we already know, native classes extend each other. For instance, `Array` extends `Object`.
همانطور که از قبل می‌دانیم، کلاس‌های نیتیو یکدیگر را تعمیم می‌دهند. برای مثال `Array` کلاس `Object` را تعمیم می‌دهد.

Normally, when one class extends another, both static and non-static methods are inherited. That was thoroughly explained in the article [](info:static-properties-methods#statics-and-inheritance).
طبیعاتا، زمانی که کلاسی کلاس دیگر را تعمیم می‌دهد، هم متدهای ایستا و هم متدهای غیر ایستا به ارث برده می‌شوند. این موضوع به طور کامل در مقاله [](info:static-properties-methods#statics-and-inheritance) توضیح داده شد.

But built-in classes are an exception. They don't inherit statics from each other.
اما کلاس‌های درون‌ساخت استثنا هستند. آن‌ها ویژگی‌های ایستا را از یکدیگر به ارث نمی‌برند.

For example, both `Array` and `Date` inherit from `Object`, so their instances have methods from `Object.prototype`. But `Array.[[Prototype]]` does not reference `Object`, so there's no, for instance, `Array.keys()` (or `Date.keys()`) static method.
برای مثال، هر دو کلاس `Array` و `Date` از `Object` ارث‌بری می‌کنند، پس نمونه‌های آن‌ها از `Object.prototype` متدهایی دارند. اما `Array.[[Prototype]]` به `Object` رجوع نمی‌کند پس برای مثال، مندهای ایستای `Array.keys()` (یا `Date.keys()`) وجود ندارند.

Here's the picture structure for `Date` and `Object`:
اینجا ساختاری تصویری برای `Date` و `Object` داریم:

![](object-date-inheritance.svg)

As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`.
همانطور که می‌بینید، بین `Date` و `Object` هیچ ارتباطی وجود ندارد. آن‌ها مستقل هستند، فقط `Date.prototype` از `Object.prototype` ارث‌بری می‌کند.

That's an important difference of inheritance between built-in objects compared to what we get with `extends`.
این یک تفاوت مهم شیءهای درون‌ساخت در مقایسه با چیزی است که از `extends` بدست می‌آوریم است.