You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remember, new objects can be created with a constructor function, like `new F()`.
3
+
لا تنسَ بأنّك يمكنك إنشاء كائنات جديدة من خلال دالّة الباني (مثل `new F() `).
4
4
5
-
If `F.prototype`is an object, then the `new`operator uses it to set `[[Prototype]]`for the new object.
5
+
لو كان `F.prototype`كائن جافاسكربت، فإن المعامِل `new`سيضبط الخاصية `[[Prototype]]`لهذا الكائن الجديد.
6
6
7
-
```smart
8
-
JavaScript had prototypal inheritance from the beginning. It was one of the core features of the language.
7
+
من بداية تضمين لغة جافاسكربت للوراثة النموذجية جعلتها من المميزات الأساسية في اللغة.
8
+
ولكن في الماضي لم يكن هنالك القدرة للوصول المباشر للوراثة النموذجية والطريقة الوحيدة الّتي حلّت محلها هي خاصية `"prototype"` في دالّة الباني. سنشرح في هذا الدرس كيفية استخدامها لأنه مازال العديد من الشيفرات البرمجية القديمة تستخدمها.
9
9
10
-
But in the old times, there was no direct access to it. The only thing that worked reliably was a `"prototype"` property of the constructor function, described in this chapter. So there are many scripts that still use it.
11
-
```
12
-
13
-
Please note that `F.prototype` here means a regular property named `"prototype"` on `F`. It sounds something similar to the term "prototype", but here we really mean a regular property with this name.
10
+
لاحظ بأنّ `F.prototype` هنا تعني وجود خاصية عادية باسم `"prototype"` للكائن `F`. ربما تفكّر وكأنها النموذج الأولي لهذا الكائن، ولكن لا... فهنا نعني حرفيًا أنها خاصية عادية لها هذا الاسم.
14
11
15
-
Here's the example:
12
+
إليك مثالًا:
16
13
17
-
```js run
14
+
```
18
15
let animal = {
19
16
eats: true
20
17
};
@@ -23,153 +20,301 @@ function Rabbit(name) {
23
20
this.name = name;
24
21
}
25
22
26
-
*!*
27
-
Rabbit.prototype= animal;
28
-
*/!*
23
+
Rabbit.prototype = animal; // هنا
29
24
30
25
let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
31
26
32
27
alert( rabbit.eats ); // true
33
28
```
34
29
35
-
Setting `Rabbit.prototype = animal`literally states the following: "When a `new Rabbit` is created, assign its `[[Prototype]]`to`animal`".
30
+
تعني التعليمة `Rabbit.prototype = animal`حرفيًا الآتي: "ما إن يُنشأ كائن `new Rabbit`، أسنِد خاصية `[[Prototype]]`له لتكون للكائن`animal`".
36
31
37
-
That's the resulting picture:
32
+
إليك الصورة الناتجة:
38
33
39
-

34
+
[proto-constructor-animal-rabbit.png]
40
35
41
-
On the picture,`"prototype"`is a horizontal arrow, meaning a regular property, and `[[Prototype]]`is vertical, meaning the inheritance of `rabbit`from`animal`.
36
+
في الصورة نرى`"prototype"`في سهم أفقي (أي أنّها خاصية عادية) بينما `[[Prototype]]`في سهم رأسي (أي أنّها توضّح وراثة كائن `rabbit`للكائن`animal`).
42
37
43
-
```smart header="`F.prototype` only used at `new F` time"
44
-
`F.prototype` property is only used when `new F` is called, it assigns `[[Prototype]]` of the new object.
38
+
إن الخاصية `F.prototype` تستخدم عند الإنشاء فقط أي عندما تستدعى تعليمة `new F` وتُسند للكائن القيمة المناسبة للخاصية `[[Prototype]]`.
39
+
في حال تغيرت الخاصية `F.prototype` مثلًا (`F.prototype = <another object>`)، عندها ستحصل الكائنات المنشأة بعد هذا التغيير على القيمة الجديدة للخاصية `[[Prototype]]` (أي الكائن الجديد)،
40
+
ولكن الكائنات القديمة مازالت تحتفظ بالقيمة القديمة.
45
41
46
-
If, after the creation, `F.prototype` property changes (`F.prototype = <another object>`), then new objects created by `new F` will have another object as `[[Prototype]]`, but already existing objects keep the old one.
47
-
```
48
-
49
-
## Default F.prototype, constructor property
42
+
## القيمة الإفتراضية للخاصية prototype في الباني
50
43
51
-
Every function has the `"prototype"` property even if we don't supply it.
44
+
لكلّ دالة خاصية `"prototype"`حتّى لو لم نقدّمها نحن.
52
45
53
-
The default `"prototype"` is an object with the only property `constructor` that points back to the function itself.
46
+
إن القيمة الإفتراضية للخاصية `"prototype"`تُشير إلى نفس الدالّة.
alert(rabbit.constructor == Rabbit); // true من prototype
87
80
```
88
81
89
-

82
+
[rabbit-prototype-constructor.png]
90
83
91
-
We can use`constructor`property to create a new object using the same constructor as the existing one.
84
+
يمكننا استعمال الخاصية`constructor`لإنشاء كائن جديد باستعمال نفس الباني الّذي أنشأ الكائن الموجود حاليًا.
92
85
93
-
Like here:
86
+
هكذا:
94
87
95
-
```js run
88
+
```
96
89
function Rabbit(name) {
97
90
this.name = name;
98
91
alert(name);
99
92
}
100
93
101
94
let rabbit = new Rabbit("White Rabbit");
102
95
103
-
*!*
96
+
// انظر
104
97
let rabbit2 = new rabbit.constructor("Black Rabbit");
105
-
*/!*
106
98
```
107
99
108
-
That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create another one of the same kind.
100
+
يُفيدنا هذا حين نكون أمام كائن ولكن لا نعرف الباني الحقيقي الّذي بناه (ربما أتى من مكتبة خارجية)، وأردنا إنشاء كائن آخر مثله.
109
101
110
-
But probably the most important thing about `"constructor"`is that...
102
+
ولكن الأمر الأهم الّذي يتعلّق بِـ `"constructor"`هو أنّ **لغة جافاسكربت نفسها لا تتأكّد من صحّة قيمة خاصية `"constructor"`.**
111
103
112
-
**...JavaScript itself does not ensure the right `"constructor"`value.**
104
+
نعم كما قرأت، الخاصية موجودة في `"prototype"`للدوالّ، وهذا كلّ ما في الأمر. إذ ستعتمد لغة جافاسكربت علينا فيما سيحدث لاحقًا.
113
105
114
-
Yes, it exists in the default `"prototype"` for functions, but that's all. What happens with it later -- is totally on us.
106
+
فمثلًا لو أردنا استبدال القيمة الإفتراضية للخاصية prototype، فلن يملك الكائن أيّ خاصية `"constructor"`.
115
107
116
-
In particular, if we replace the default prototype as a whole, then there will be no `"constructor"` in it.
108
+
مثال:
117
109
118
-
For instance:
119
-
120
-
```js run
110
+
```
121
111
function Rabbit() {}
122
112
Rabbit.prototype = {
123
113
jumps: true
124
114
};
125
115
126
116
let rabbit = new Rabbit();
127
-
*!*
117
+
// لاحظ
128
118
alert(rabbit.constructor === Rabbit); // false
129
-
*/!*
130
119
```
131
120
132
-
So, to keep the right `"constructor"`we can choose to add/remove properties to the default `"prototype"`instead of overwriting it as a whole:
121
+
ولهذا لنُبقي على خاصية `"constructor"`الصحيحة يمكننا إضافة الخاصيات وإزالتها من كائن `"prototype"`الإفتراضي بدل الطريقة السابقة. هكذا:
133
122
134
-
```js
123
+
```
135
124
function Rabbit() {}
136
125
137
-
//Not overwrite Rabbit.prototype totally
138
-
//just add to it
126
+
// بدل الكتابة على كلّ Rabbit.prototype
127
+
// نُضيف ما نريد إليه
139
128
Rabbit.prototype.jumps = true
140
-
//the default Rabbit.prototype.constructor is preserved
129
+
// هكذا تبقى خاصية Rabbit.prototype.constructor الإفتراضية محفوظة
141
130
```
142
131
143
-
Or, alternatively, recreate the `constructor`property manually:
132
+
أو يمكننا (لو أردنا) إعادة إنشاء الخاصية `constructor`يدويًا:
144
133
145
-
```js
134
+
```
146
135
Rabbit.prototype = {
147
136
jumps: true,
148
-
*!*
149
-
constructor: Rabbit
150
-
*/!*
137
+
constructor: Rabbit // هنا
151
138
};
152
139
153
-
//now constructor is also correct, because we added it
140
+
// الآن سيكون المُنشِئ صحيحًا إذ أنّا من أضفناه
154
141
```
155
142
156
143
157
-
## Summary
144
+
## خلاصة
158
145
159
-
In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it.
146
+
شرحنا في هذا الفصل سريعًا طريقة ضبط كائن `[[Prototype]]`للكائنات الّتي أنشأتها بدالّة الباني. سنرى لاحقًا أنماط متقدّمة في البرمجة تعتمد على هذا الطريقة.
160
147
161
-
Everything is quite simple, just a few notes to make things clear:
148
+
ما أخذناه بسيط، ولكن بعض الأمور نوضّحها ثانيةً للتأكّد:
162
149
163
-
- The `F.prototype` property (don't mistake it for `[[Prototype]]`) sets `[[Prototype]]` of new objects when `new F()` is called.
164
-
- The value of `F.prototype` should be either an object or `null`: other values won'twork.
165
-
-The`"prototype"`propertyonlyhassuchaspecialeffectwhensetonaconstructor function, and invoked with `new`.
150
+
-تضبط الخاصية `F.prototype`(لا تظنّها كائن `[[Prototype]]`) لكائنٍ ما الخاصية `[[Prototype]]`لكلّ الكائنات الجديدة متى استدعيت `new F()`.
151
+
-يجب أن تكون قيمة `F.prototype`إمّا كائنًا أو `null`، ولن تعمل أيّة قيم أخرى.
152
+
-هذا التأثير للخاصية `"prototype"`موجود فقط حين يُضبط في دالة الباني وحين يُنفّذ بتعليمة`new`.
166
153
167
-
On regular objects the `prototype` is nothing special:
168
-
```js
154
+
في الكائنات العادية ليست بخاصية خاصة جدًا:
155
+
```
169
156
let user = {
170
157
name: "John",
171
-
prototype: "Bla-bla" // no magic at all
158
+
prototype: "Bla-bla" // نزعنا السحر
159
+
};
160
+
```
161
+
162
+
لكلّ الدوالّ مبدئيًا `F.prototype = { constructor: F }`، فيمكننا أن نأخذ باني معين من كائن ما بالدخول إلى الخاصية `"constructor"` الخاصة به.
163
+
164
+
## تمارين
165
+
### تغيير الخاصية ”prototype“
166
+
_الأهمية: 5_
167
+
168
+
أنشأنا في الشيفرة أدناه كائنًا جديدًا `new Rabbit` وحاولنا بعدها تعديل الخاصية prototype لهذا الكائن.
169
+
170
+
بادئ ذي بدء، كانت الشيفرة:
171
+
172
+
```
173
+
function Rabbit() {}
174
+
Rabbit.prototype = {
175
+
eats: true
172
176
};
177
+
178
+
let rabbit = new Rabbit();
179
+
180
+
alert( rabbit.eats ); // true
181
+
```
182
+
183
+
184
+
1. وأضفنا سلسلة نصية أخرى (عليها علامة). ماذا سيعرض التابِع `alert`؟
185
+
186
+
```
187
+
function Rabbit() {}
188
+
Rabbit.prototype = {
189
+
eats: true
190
+
};
191
+
192
+
let rabbit = new Rabbit();
193
+
194
+
Rabbit.prototype = {}; // (*)
195
+
196
+
alert( rabbit.eats ); // ?
197
+
```
198
+
199
+
2. وماذا لو... كانت الشيفرة كهذه (استبدلنا سطرًا فيها)؟
200
+
201
+
```
202
+
function Rabbit() {}
203
+
Rabbit.prototype = {
204
+
eats: true
205
+
};
206
+
207
+
let rabbit = new Rabbit();
208
+
209
+
Rabbit.prototype.eats = false; // (*)
210
+
211
+
alert( rabbit.eats ); // ?
212
+
```
213
+
214
+
3. وماذا عن هذه (استبدلنا سطرًا أيضًا)؟
215
+
216
+
```
217
+
function Rabbit() {}
218
+
Rabbit.prototype = {
219
+
eats: true
220
+
};
221
+
222
+
let rabbit = new Rabbit();
223
+
224
+
delete rabbit.eats; // (*)
225
+
226
+
alert( rabbit.eats ); // ?
227
+
```
228
+
229
+
4. وهذه... أيضًا:
230
+
231
+
```
232
+
function Rabbit() {}
233
+
Rabbit.prototype = {
234
+
eats: true
235
+
};
236
+
237
+
let rabbit = new Rabbit();
238
+
239
+
delete Rabbit.prototype.eats; // (*)
240
+
241
+
alert( rabbit.eats ); // ?
242
+
```
243
+
#### الحل
244
+
الإجابات:
245
+
246
+
1. `true`.
247
+
248
+
عملية الإسناد على `Rabbit.prototype` تضع الخاصية `[[Prototype]]` للكائنات الجديدة، ولكنّها لا تعدّل على الكائنات الموجودة مسبقًا.
249
+
250
+
2. `false`.
251
+
عملية الإسناد تكون من خلال الخاصية `Rabbit.prototype`، إن الخاصية المشار إليها هنا `Rabbit.prototype` ليست مكررًا، وإنما بقيت يُشار إليها من خلال `Rabbit.prototype` و الخاصية `[[Prototype]]` للكائن `rabbit`.
252
+
253
+
لذا حين نغيّر المحتوى في الطريقة الأولى سنرى النتائج في الطريقة الثانية.
254
+
255
+
3. `true`.
256
+
كلّ عمليات الحذف تطبق مباشرة على الكائن. تحاول هذه التعليمة `delete rabbit.eats` حذف الخاصية المخصصة للكائن `rabbit` ولكنها ليست لها. لذا العملية لن يكون لها أي تأثير.
257
+
258
+
259
+
4. `undefined`.
260
+
261
+
حُذفت الخاصية `eats` من كائن prototype وما عادت موجودة بعد الآن.
262
+
263
+
### إنشاء كائن جديد من خلال نفس باني لكائنٍ آخر
264
+
_الأهمية: 5_
265
+
266
+
تخيّل بأنّ لدينا الكائن الفريد `obj` وأنشأته بدالة الباني، ولكننا... لا نعرف أيّ دالة هذه، ولكن مع ذلك نريد استعمال نفس الباني لإنشاء كائن جديد آخر.
267
+
268
+
أيمكن لهذه الشيفرة إنجاز المهمة؟
269
+
270
+
```
271
+
let obj2 = new obj.constructor();
272
+
```
273
+
274
+
اكتب مثالين باستخدام بانيين للكائن `obj`، واحدًا يعمل مع الشيفرة أعلاه، وواحدًا لا يعمل له.
275
+
#### الحل
276
+
يمكن أن نستعمل هذه الطريقة لو كنّا متأكدين مئة بالمئة بأنّ خاصية `"constructor"` تحمل القيمة الصحيحة.
277
+
278
+
فمثلًا لو لم نعدّل على `"prototype"` المبدئية فستعمل هذه الشيفرة بلا ريب:
279
+
280
+
```
281
+
function User(name) {
282
+
this.name = name;
283
+
}
284
+
285
+
let user = new User('John');
286
+
let user2 = new user.constructor('Pete');
287
+
288
+
alert( user2.name ); // Pete (عملت!)
289
+
```
290
+
291
+
نفذت الشيفرة تنفيذًا صحيحًا إذ أنّ `User.prototype.constructor == User`.
292
+
293
+
ولكن... لو أتى أحدهم مثلًا وكتب على `User.prototype` ونسي إعادة إنشاء `constructor` لتُشير إلى كائن المستخدم `User`، فلن تعمل الشيفرة.
294
+
295
+
مثال:
296
+
297
+
```
298
+
function User(name) {
299
+
this.name = name;
300
+
}
301
+
User.prototype = {}; // (*)
302
+
303
+
let user = new User('John');
304
+
let user2 = new user.constructor('Pete');
305
+
306
+
alert( user2.name ); // undefined
173
307
```
174
308
175
-
By default all functions have `F.prototype = { constructor: F }`, so we can get the constructor of an object by accessing its `"constructor"` property.
309
+
لمَ قيمة `user2.name` هي `undefined`؟
310
+
311
+
إليك طريقة عمل تعليمة `new user.constructor('Pete')`:
312
+
313
+
1. أولًا، تبحث عن المُنشِئ `constructor` داخل `user`، ولا تجده.
314
+
2. ثمّ تتبع سلسلة prototype وتجد prototype الكائن `user` هو `User.prototype`، وأيضًا لا تجده.
315
+
3. قيمة `User.prototype` ما هي إلّا كائنًا فارغًا `{}`، و قيمة الخاصية prototype لهذا الكائن هي `Object.prototype`، وهنا وجدنا `Object.prototype.constructor == Object` بذلك استعملناه.
316
+
317
+
وفي نهاية الأمر، لدينا التعليمة `let user2 = new Object('Pete')` إذ أنّ الباني الخاص بالكائن `Object` يتجاهل الوسطاء وينشىء دائمًا كائنًا فارغًا. بطريقة مشابهة جدًا للتعليمة `let user2 = {}` والّتي أنشأت لنا الكائن `user2` في نهاية الأمر.
318
+
319
+
ترجمة -وبتصرف- للفصل [F.prototype](https://javascript.info/function-prototype) من كتاب [The JavaScript language](https://javascript.info/js)
0 commit comments