Skip to content
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

Using __proto__ in object literals is not deprecated #3014

Closed
wants to merge 1 commit into from
Closed
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
23 changes: 12 additions & 11 deletions 1-js/08-prototypes/04-prototype-methods/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@

In the first chapter of this section, we mentioned that there are modern methods to setup a prototype.

The `__proto__` is considered outdated and somewhat deprecated (in browser-only part of the JavaScript standard).
Setting or reading the prototype with `obj.__proto__` is considered outdated and somewhat deprecated (in browser-only part of the JavaScript standard).

The modern methods are:

- [Object.create(proto, [descriptors])](mdn:js/Object/create) -- creates an empty object with given `proto` as `[[Prototype]]` and optional property descriptors.
- [Object.getPrototypeOf(obj)](mdn:js/Object/getPrototypeOf) -- returns the `[[Prototype]]` of `obj`.
- [Object.setPrototypeOf(obj, proto)](mdn:js/Object/setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto`.

These should be used instead of `__proto__`.
These should be used instead of `.__proto__`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to obj.__proto__? Clashes with above paragraph when it's referenced as obj.__proto__ rather.


For instance:

Expand All @@ -22,7 +21,9 @@ let animal = {

// create a new object with animal as a prototype
*!*
let rabbit = Object.create(animal);
let rabbit = {
__proto__: animal,
};
*/!*

alert(rabbit.eats); // true
Expand All @@ -36,7 +37,7 @@ Object.setPrototypeOf(rabbit, {}); // change the prototype of rabbit to {}
*/!*
```

`Object.create` has an optional second argument: property descriptors. We can provide additional properties to the new object there, like this:
There is also a method called [Object.create(proto, [descriptors])](mdn:js/Object/create) which creates an empty object with given `proto` as `[[Prototype]]` and optional property descriptors. We can provide additional properties to the new object in the second argument, like this:

```js run
let animal = {
Expand Down Expand Up @@ -131,7 +132,7 @@ Now, if we intend to use an object as an associative array and be free of such p

```js run
*!*
let obj = Object.create(null);
let obj = { __proto__: null };
*/!*

let key = prompt("What's the key?", "__proto__");
Expand All @@ -140,7 +141,7 @@ obj[key] = "some value";
alert(obj[key]); // "some value"
```

`Object.create(null)` creates an empty object without a prototype (`[[Prototype]]` is `null`):
`{ __proto__: null }` creates an empty object without a prototype (`[[Prototype]]` is `null`):

![](object-prototype-null.svg)

Expand All @@ -152,7 +153,7 @@ A downside is that such objects lack any built-in object methods, e.g. `toString

```js run
*!*
let obj = Object.create(null);
let obj = { __proto__: null };
*/!*

alert(obj); // Error (no toString)
Expand All @@ -164,7 +165,7 @@ Note that most object-related methods are `Object.something(...)`, like `Object.


```js run
let chineseDictionary = Object.create(null);
let chineseDictionary = { __proto__: null };
chineseDictionary.hello = "你好";
chineseDictionary.bye = "再见";

Expand All @@ -181,7 +182,7 @@ Modern methods to set up and directly access the prototype are:

The built-in `__proto__` getter/setter is unsafe if we'd want to put user-generated keys into an object. Just because a user may enter `"__proto__"` as the key, and there'll be an error, with hopefully light, but generally unpredictable consequences.

So we can either use `Object.create(null)` to create a "very plain" object without `__proto__`, or stick to `Map` objects for that.
So we can either use `{ __proto__: null }` to create a "very plain" object without `__proto__`, or stick to `Map` objects for that.

Also, `Object.create` provides an easy way to shallow-copy an object with all descriptors:

Expand All @@ -191,7 +192,7 @@ let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescr

We also made it clear that `__proto__` is a getter/setter for `[[Prototype]]` and resides in `Object.prototype`, just like other methods.

We can create an object without a prototype by `Object.create(null)`. Such objects are used as "pure dictionaries", they have no issues with `"__proto__"` as the key.
We can create an object without a prototype by `{ __proto__: null }`. Such objects are used as "pure dictionaries", they have no issues with `"__proto__"` as the key.

Other methods:

Expand Down