Merge pull request #1504 from hrodward/patch-24

Update article.md
This commit is contained in:
Ilya Kantor 2019-10-25 14:20:31 +03:00 committed by GitHub
commit fac4413c60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -99,12 +99,12 @@ alert(f.__proto__.__proto__ == Object.prototype); // true, inherit from objects
The most intricate thing happens with strings, numbers and booleans. 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, then temporary wrapper objects are created using built-in constructors `String`, `Number`, `Boolean`, they provide the methods and disappear. 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.
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`. 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`.
```warn header="Values `null` and `undefined` have no object wrappers" ```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 too. 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.
``` ```
## Changing native prototypes [#native-prototype-change] ## Changing native prototypes [#native-prototype-change]
@ -129,9 +129,9 @@ 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.** **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 JavaScript specification, but is not yet supported by current JavaScript engine. 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.
Then we may implement it manually and populate the built-in prototype with it. We may then implement it manually and populate the built-in prototype with it.
For instance: For instance:
@ -144,7 +144,7 @@ if (!String.prototype.repeat) { // if there's no such method
// actually, the code should be a little bit more complex than that // actually, the code should be a little bit more complex than that
// (the full algorithm is in the specification) // (the full algorithm is in the specification)
// but even an imperfect polyfill is often considered good enough for use // but even an imperfect polyfill is often considered good enough
return new Array(n + 1).join(this); return new Array(n + 1).join(this);
}; };
} }
@ -179,18 +179,18 @@ obj.join = Array.prototype.join;
alert( obj.join(',') ); // Hello,world! 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 that the object is indeed the array. And many built-in methods are like that. 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.
Another possibility is to inherit by setting `obj.__proto__` to `Array.prototype`, so all `Array` methods are automatically available in `obj`. Another possibility is to inherit by setting `obj.__proto__` to `Array.prototype`, so all `Array` methods are automatically available in `obj`.
But that's impossible if `obj` already inherits from another object. Remember, we only can inherit from one object at a time. But that's impossible if `obj` already inherits from another object. Remember, we only can inherit from one object at a time.
Borrowing methods is flexible, it allows to mix functionality from different objects if needed. Borrowing methods is flexible, it allows to mix functionalities from different objects if needed.
## Summary ## Summary
- All built-in objects follow the same pattern: - All built-in objects follow the same pattern:
- The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype` etc). - The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype`, etc.)
- The object itself stores only the data (array items, object properties, the date). - 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`, `Boolean.prototype`. Only `undefined` and `null` do not have wrapper objects. - 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. Probably the only allowable case is when we add-in a new standard, but not yet supported by the engine JavaScript method. - 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