From 6632dee9ad782f9e8642702926f02320cf368d74 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 11:34:45 +0800 Subject: [PATCH 1/9] Add __proto__ key initializer to "Inheritance and the prototype chain" --- .../index.md | 77 ++++++++++++++----- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index da3c9d5696d524a..e80aa0314e9a2dc 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -259,6 +259,13 @@ function f() { // Functions inherit from Function.prototype // (which has methods call, bind, etc.) // f ---> Function.prototype ---> Object.prototype ---> null + +const p = { b: 2, __proto__: o }; + +// It is possible to point the newly created object's [[Prototype]] to another +// object via the __proto__ literal property. (Not to be confused with +// Object.prototype.__proto__ accessors) +// p ---> o ---> Object.prototype ---> null ``` ### With a constructor @@ -396,7 +403,7 @@ Note: It is **not** enough to check whether a property is [`undefined`](/en-US/d ### Summary of methods for extending the prototype chain -Here are all 4 ways and their pros/cons. All of the examples listed below create exactly the same resulting `inst` object (thus logging the same results to the console), except in different ways. +Here are all 5 ways and their pros/cons. All of the examples listed below create exactly the same resulting `inst` object (thus logging the same results to the console), except in different ways. #### #1: New initialization @@ -480,7 +487,7 @@ const proto = Object.create( bar.prototype = proto; const inst = new bar(); console.log(inst.foo_prop); -console.log(inst.bar_prop) +console.log(inst.bar_prop); ``` @@ -540,7 +547,7 @@ const proto = Object.setPrototypeOf( bar.prototype = proto; const inst = new bar(); console.log(inst.foo_prop); -console.log(inst.bar_prop) +console.log(inst.bar_prop); ```
@@ -573,58 +580,86 @@ console.log(inst.bar_prop) #### #4: Setting the {{jsxref("Object/proto","__proto__")}} property ```js -// Technique 1 function A() {} A.prototype.foo_prop = 'foo val'; function bar() {} -const proto = { - bar_prop: 'bar val', - __proto__: A.prototype -}; +const proto = { bar_prop: 'bar val' }; +proto.__proto__ = A.prototype; bar.prototype = proto; const inst = new bar(); console.log(inst.foo_prop); console.log(inst.bar_prop); ``` +
+ + + + + + + + + + + +
+ Pros and cons of setting the + {{jsxref("Object/proto","__proto__")}} property +
Pro(s) + Supported in all modern browsers. Setting + {{jsxref("Object/proto","__proto__")}} to something that + is not an object only fails silently. It does not throw an exception. +
Con(s) + Non-performant and deprecated. Many browsers optimize the prototype and + try to guess the location of the method in the memory when calling an + instance in advance; but setting the prototype dynamically disrupts all + those optimizations and can even force some browsers to recompile for + de-optimization of your code, to make it work according to the specs. + Not supported in IE10 and below. +
+ +#### #5: Using the __proto__ key in {{jsxref("Object_initializer")}} + ```js -// Technique 2 const inst = { __proto__: { bar_prop: 'bar val', __proto__: { foo_prop: 'foo val', + // This can be omitted __proto__: Object.prototype } } }; console.log(inst.foo_prop); -console.log(inst.bar_prop) +console.log(inst.bar_prop); ``` From 077dfed6e2814720b80cddf4eff6a65ce11c23b7 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 11:42:45 +0800 Subject: [PATCH 2/9] Update index.md --- .../inheritance_and_the_prototype_chain/index.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index e80aa0314e9a2dc..c40630b2911416d 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -580,6 +580,7 @@ console.log(inst.bar_prop); #### #4: Setting the {{jsxref("Object/proto","__proto__")}} property ```js +// Technique 1 function A() {} A.prototype.foo_prop = 'foo val'; function bar() {} @@ -591,6 +592,15 @@ console.log(inst.foo_prop); console.log(inst.bar_prop); ``` +```js +// Technique 2 +const inst = {}; +inst.__proto__ = { bar_prop: 'bar val' }; +inst.__proto__.__proto__ = { foo_prop: 'foo val' }; +console.log(inst.foo_prop); +console.log(inst.bar_prop); +``` +
- Pros and cons of setting the - {{jsxref("Object/proto","__proto__")}} property + Pros and cons of using the __proto__ key in {{jsxref("Object_initializer")}}
Pro(s) - Supported in all modern browsers. Setting - {{jsxref("Object/proto","__proto__")}} to something that - is not an object only fails silently. It does not throw an exception. + Supported in all modern browsers. Pointing the __proto__ + key to something that is not an object only fails silently without + throwing an exception. Contrary to the + {{jsxref("Object/proto","__proto__")}} setter, __proto__ + in object literal initializers is standardized and optimized, and can + even be more performant than {{jsxref("Object.create")}}. Declaring + extra own properties on the object at creation is more ergonomic than + {{jsxref("Object.create")}}.
Con(s) - Non-performant and deprecated. Many browsers optimize the prototype and - try to guess the location of the method in the memory when calling an - instance in advance; but setting the prototype dynamically disrupts all - those optimizations and can even force some browsers to recompile for - de-optimization of your code, to make it work according to the specs. - Not supported in IE10 and below. + Not supported in IE10 and below. Likely to be confused with + {{jsxref("Object/proto","__proto__")}} for people unaware of the + difference.
Pros and cons of setting the From 22e330ad271b96ab06bf1d5cfc366b93ac4869a4 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 13:16:23 +0800 Subject: [PATCH 3/9] Update files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md Co-authored-by: Michael[tm] Smith --- .../web/javascript/inheritance_and_the_prototype_chain/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index c40630b2911416d..68c4145b08b5acb 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -629,7 +629,7 @@ console.log(inst.bar_prop);
-#### #5: Using the __proto__ key in {{jsxref("Object_initializer")}} +#### #5: Using the __proto__ key in an object initializer ```js const inst = { From 427cf6c825f5811474a0830a918e4228fddb87df Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 13:33:27 +0800 Subject: [PATCH 4/9] fix broken link --- .../javascript/inheritance_and_the_prototype_chain/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index 68c4145b08b5acb..fa96a81ea5e53d6 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -629,7 +629,7 @@ console.log(inst.bar_prop); -#### #5: Using the __proto__ key in an object initializer +#### #5: Using the __proto__ key in object initializers ```js const inst = { @@ -648,7 +648,7 @@ console.log(inst.bar_prop); From aaa22900861e445107330df4e45a9e30085cf588 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 13:41:22 +0800 Subject: [PATCH 5/9] fix again --- .../inheritance_and_the_prototype_chain/index.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index fa96a81ea5e53d6..1384ac10f2e8aab 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -262,9 +262,9 @@ function f() { const p = { b: 2, __proto__: o }; -// It is possible to point the newly created object's [[Prototype]] to another -// object via the __proto__ literal property. (Not to be confused with -// Object.prototype.__proto__ accessors) +// It is possible to point the newly created object's [[Prototype]] to +// another object via the __proto__ literal property. (Not to be confused +// with Object.prototype.__proto__ accessors) // p ---> o ---> Object.prototype ---> null ``` @@ -648,7 +648,7 @@ console.log(inst.bar_prop);
- Pros and cons of using the __proto__ key in {{jsxref("Object_initializer")}} + Pros and cons of using the __proto__ key in [object initializers](/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer)
@@ -657,7 +657,7 @@ console.log(inst.bar_prop); Supported in all modern browsers. Pointing the __proto__ key to something that is not an object only fails silently without throwing an exception. Contrary to the - {{jsxref("Object/proto","__proto__")}} setter, __proto__ + {{jsxref("Object/proto")}} setter, __proto__ in object literal initializers is standardized and optimized, and can even be more performant than {{jsxref("Object.create")}}. Declaring extra own properties on the object at creation is more ergonomic than @@ -668,8 +668,7 @@ console.log(inst.bar_prop); From af9fa248e3028a988c6e8b8c88809f7ed4356234 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 13:44:00 +0800 Subject: [PATCH 6/9] Correct title --- .../web/javascript/inheritance_and_the_prototype_chain/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index 1384ac10f2e8aab..0dae147e91f2d22 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -629,7 +629,7 @@ console.log(inst.bar_prop);
- Pros and cons of using the __proto__ key in [object initializers](/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) + Pros and cons of using the __proto__ key in object initializers
Con(s) Not supported in IE10 and below. Likely to be confused with - {{jsxref("Object/proto","__proto__")}} for people unaware of the - difference. + {{jsxref("Object/proto")}} for people unaware of the difference.
-#### #5: Using the __proto__ key in object initializers +#### #5: Using the `__proto__` key in object initializers ```js const inst = { From 52d59ab436ab75a51fec9727d3898a5c2e90535f Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 13:53:13 +0800 Subject: [PATCH 7/9] I messed up again --- .../javascript/inheritance_and_the_prototype_chain/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index 0dae147e91f2d22..0a8eb7393682f60 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -657,7 +657,7 @@ console.log(inst.bar_prop); Supported in all modern browsers. Pointing the __proto__ key to something that is not an object only fails silently without throwing an exception. Contrary to the - {{jsxref("Object/proto")}} setter, __proto__ + {{jsxref("Object/proto", "Object.prototype.__proto__")}} setter, __proto__ in object literal initializers is standardized and optimized, and can even be more performant than {{jsxref("Object.create")}}. Declaring extra own properties on the object at creation is more ergonomic than @@ -668,7 +668,8 @@ console.log(inst.bar_prop); Con(s) Not supported in IE10 and below. Likely to be confused with - {{jsxref("Object/proto")}} for people unaware of the difference. + {{jsxref("Object/proto", "Object.prototype.__proto__")}} accessors for + people unaware of the difference. From f63116cb8fa55ebbdac5cb7698d0434276bc0da0 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 14:01:31 +0800 Subject: [PATCH 8/9] Highlight harder that `Object.prototype.__proto__` should be avoided --- .../index.md | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index 0a8eb7393682f60..5d4599fdd3f9960 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -566,12 +566,13 @@ console.log(inst.bar_prop); Con(s) - Ill-performing. Should be deprecated. Many browsers optimize the - prototype and try to guess the location of the method in memory when - calling an instance in advance; but setting the prototype dynamically - disrupts all those optimizations. It might cause some browsers to - recompile your code for de-optimization, to make it work according to - the specs. Not supported in IE8 and below. + Ill-performing. Should be avoided if it's possible to set the prototype + at object creation time. Many browsers optimize the prototype and try to + guess the location of the method in memory when calling an instance in + advance; but setting the prototype dynamically disrupts all those + optimizations. It might cause some browsers to recompile your code for + de-optimization, to make it work according to the specs. Not supported + in IE8 and below. @@ -623,7 +624,10 @@ console.log(inst.bar_prop); instance in advance; but setting the prototype dynamically disrupts all those optimizations and can even force some browsers to recompile for de-optimization of your code, to make it work according to the specs. - Not supported in IE10 and below. + Not supported in IE10 and below. The {{jsxref("Object/proto","__proto__")}} + setter is normative optional, so it may not work across all platforms. + You should almost always use {{jsxref("Object.setPrototypeOf")}} + instead. @@ -657,10 +661,11 @@ console.log(inst.bar_prop); Supported in all modern browsers. Pointing the __proto__ key to something that is not an object only fails silently without throwing an exception. Contrary to the - {{jsxref("Object/proto", "Object.prototype.__proto__")}} setter, __proto__ - in object literal initializers is standardized and optimized, and can - even be more performant than {{jsxref("Object.create")}}. Declaring - extra own properties on the object at creation is more ergonomic than + {{jsxref("Object/proto", "Object.prototype.__proto__")}} setter, + __proto__ in object literal initializers is standardized + and optimized, and can even be more performant than + {{jsxref("Object.create")}}. Declaring extra own properties on the + object at creation is more ergonomic than {{jsxref("Object.create")}}. From d651563f44974b5d76b85de64154751fa6c8c004 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 14:48:25 +0800 Subject: [PATCH 9/9] Include comments and callouts --- .../javascript/inheritance_and_the_prototype_chain/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md index 5d4599fdd3f9960..8b2b1af4a67ead1 100644 --- a/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md +++ b/files/en-us/web/javascript/inheritance_and_the_prototype_chain/index.md @@ -580,12 +580,15 @@ console.log(inst.bar_prop); #### #4: Setting the {{jsxref("Object/proto","__proto__")}} property +> **Warning:** `Object.prototype.__proto__` accessors are **non-standard** and deprecated. You should almost always use `Object.setPrototypeOf` instead. + ```js // Technique 1 function A() {} A.prototype.foo_prop = 'foo val'; function bar() {} const proto = { bar_prop: 'bar val' }; +// DON'T USE THIS: for example only. proto.__proto__ = A.prototype; bar.prototype = proto; const inst = new bar(); @@ -596,6 +599,7 @@ console.log(inst.bar_prop); ```js // Technique 2 const inst = {}; +// DON'T USE THIS: for example only. inst.__proto__ = { bar_prop: 'bar val' }; inst.__proto__.__proto__ = { foo_prop: 'foo val' }; console.log(inst.foo_prop); @@ -635,6 +639,8 @@ console.log(inst.bar_prop); #### #5: Using the `__proto__` key in object initializers +> **Note:** This is not to be confused with the aforementioned `Object.prototype.__proto__` accessors. `__proto__` in object literals is standardized and optimized. + ```js const inst = { __proto__: {