This commit is contained in:
Ilya Kantor 2019-07-18 12:24:31 +03:00
parent 0b55d45daf
commit 3caa91137e
8 changed files with 21 additions and 33 deletions

View file

@ -11,7 +11,7 @@ But being that formalized, it's difficult to understand at first. So if you need
The latest draft is at <https://tc39.es/ecma262/>. The latest draft is at <https://tc39.es/ecma262/>.
To read about new bleeding-edge features, that are "almost standard", see proposals at <https://github.com/tc39/proposals>. To read about new bleeding-edge features, including those that are "almost standard" (so-called "stage 3"), see proposals at <https://github.com/tc39/proposals>.
Also, if you're in developing for the browser, then there are other specs covered in the [second part](info:browser-environment) of the tutorial. Also, if you're in developing for the browser, then there are other specs covered in the [second part](info:browser-environment) of the tutorial.
@ -28,7 +28,7 @@ Also, if you're in developing for the browser, then there are other specs covere
Also, we can use an internet search with phrases such as "RegExp MSDN" or "RegExp MSDN jscript". Also, we can use an internet search with phrases such as "RegExp MSDN" or "RegExp MSDN jscript".
## Feature support ## Compatibility tables
JavaScript is a developing language, new features get added regularly. JavaScript is a developing language, new features get added regularly.

View file

@ -179,7 +179,7 @@ Modern methods to setup and directly access the prototype are:
- [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter). - [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj` (same as `__proto__` getter).
- [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter). - [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto` (same as `__proto__` setter).
The built-in `__proto__` getter/setter is unsafe if we'd want to put user-generated keys in to an object. Just because a user may enter "__proto__" as the key, and there'll be an error with hopefully easy, but generally unpredictable consequences. The built-in `__proto__` getter/setter is unsafe if we'd want to put user-generated keys in to 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 `Object.create(null)` to create a "very plain" object without `__proto__`, or stick to `Map` objects for that.
@ -189,6 +189,11 @@ Also, `Object.create` provides an easy way to shallow-copy an object with all de
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)); let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
``` ```
We also made it clear that `__proto__` is a getter/setter for `[[Prototype]]` and resides in `Object.prototype`, just as 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.
Other methods:
- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs. - [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs.
- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic keys. - [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic keys.
@ -196,8 +201,4 @@ let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescr
- [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) -- returns an array of all own keys. - [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) -- returns an array of all own keys.
- [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) key named `key`. - [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) key named `key`.
We also made it clear that `__proto__` is a getter/setter for `[[Prototype]]` and resides in `Object.prototype`, just as 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.
All methods that return object properties (like `Object.keys` and others) -- return "own" properties. If we want inherited ones, then we can use `for..in`. All methods that return object properties (like `Object.keys` and others) -- return "own" properties. If we want inherited ones, then we can use `for..in`.

View file

@ -70,21 +70,14 @@ Built-in objects have their own static methods, for instance `Object.keys`, `Arr
As we already know, native classes extend each other. For instance, `Array` extends `Object`. As we already know, native classes extend each other. For instance, `Array` extends `Object`.
Normally, when one class extends another, both static and non-static methods are inherited. Normally, when one class extends another, both static and non-static methods are inherited. That was thoroughly explained in the chapter [](info:static-properties-methods#statics-and-inheritance).
So, if `Rabbit extends Animal`, then:
1. `Rabbit.methods` are callable for `Animal.methods`, because `Rabbit.[[Prototype]] = Animal`.
2. `new Rabbit().methods` are also available, because `Rabbit.prototype.[[Prototype]] = Animal.prototype`.
That's thoroughly explained in the chapter [](info:static-properties-methods#statics-and-inheritance).
But built-in classes are an exception. They don't inherit statics from each other. 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 point to `Object`. So there's `Object.keys()`, but not `Array.keys()` and `Date.keys()`. 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 `Array.keys()` and `Date.keys()` static methods.
Here's the picture structure for `Date` and `Object`: Here's the picture structure for `Date` and `Object`:
![](object-date-inheritance.png) ![](object-date-inheritance.png)
Note, there's no link between `Date` and `Object`. Both `Object` and `Date` exist independently. `Date.prototype` inherits from `Object.prototype`, but that's all. As you can see, there's no link between `Date` and `Object`. They are independent, only `Date.prototype` inherits from `Object.prototype`.

View file

@ -107,7 +107,7 @@ As `super` looks for parent methods in `[[HomeObject]].[[Prototype]]`, that mean
Now let's make a mixin for real life. Now let's make a mixin for real life.
An important feature of many browser objects (not only) is that they can generate events. Events is a great way to "broadcast information" to anyone who wants it. So let's make a mixin that allows to easily add event-related functions to any class/object. An important feature of many browser objects (for instance) is that they can generate events. Events is a great way to "broadcast information" to anyone who wants it. So let's make a mixin that allows to easily add event-related functions to any class/object.
- The mixin will provide a method `.trigger(name, [...data])` to "generate an event" when something important happens to it. The `name` argument is a name of the event, optionally followed by additional arguments with event data. - The mixin will provide a method `.trigger(name, [...data])` to "generate an event" when something important happens to it. The `name` argument is a name of the event, optionally followed by additional arguments with event data.
- Also the method `.on(name, handler)` that adds `handler` function as the listener to events with the given name. It will be called when an event with the given `name` triggers, and get the arguments from `.trigger` call. - Also the method `.on(name, handler)` that adds `handler` function as the listener to events with the given name. It will be called when an event with the given `name` triggers, and get the arguments from `.trigger` call.

View file

@ -1,4 +1,3 @@
# Generators # Generators
Regular functions return only one, single value (or nothing). Regular functions return only one, single value (or nothing).
@ -224,8 +223,6 @@ let range = {
alert( [...range] ); // 1,2,3,4,5 alert( [...range] ); // 1,2,3,4,5
``` ```
The `range` object is now iterable.
That works, because `range[Symbol.iterator]()` now returns a generator, and generator methods are exactly what `for..of` expects: That works, because `range[Symbol.iterator]()` now returns a generator, and generator methods are exactly what `for..of` expects:
- it has `.next()` method - it has `.next()` method
- that returns values in the form `{value: ..., done: true/false}` - that returns values in the form `{value: ..., done: true/false}`

View file

@ -1,4 +1,3 @@
# Dynamic imports # Dynamic imports
Export and import statements that we covered in previous chapters are called "static". Export and import statements that we covered in previous chapters are called "static".
@ -65,10 +64,9 @@ let {hi, bye} = await import('./say.js');
hi(); hi();
bye(); bye();
``` ```
Or, for the default export: Or, if `say.js` has the default export:
```js ```js
// 📁 say.js // 📁 say.js
@ -77,12 +75,12 @@ export default function() {
} }
``` ```
To import it, we need to get `default` property of the module object, as explained in the [previous chapter](info:import-export). ...Then, in order to access it, we can use `default` property of the module object, as explained in the [previous chapter](info:import-export).
So, the dynamic import will be like this: So, the dynamic import will be like this:
```js ```js
let {default: say} = await import('./say.js'); // map .default to say variable let {default: say} = await import('./say.js'); // save .default property in say variable
say(); say();
``` ```
@ -91,12 +89,12 @@ Here's the full example:
[codetabs src="say" current="index.html"] [codetabs src="say" current="index.html"]
So, dynamic imports are very simple to use, and they allow to import modules at run-time. ```smart
Dynamic imports work in regular scripts, they don't require `script type="module"`.
Also, dynamic imports work in regular scripts, they don't require `script type="module"`. ```
```smart ```smart
Although `import()` looks like a function call, it's a special syntax that just happens to use parentheses (similar to `super()`). Although `import()` looks like a function call, it's a special syntax that just happens to use parentheses (similar to `super()`).
That means that import doesn't inherit from `Function.prototype` so we cannot call or apply it. So we can't copy `import` to a variable or use `.call/apply` with it.
``` ```

View file

@ -1,4 +1,3 @@
# Proxy and Reflect # Proxy and Reflect
A *proxy* wraps another object and intercepts operations, like reading/writing properties and others, optionally handling them on its own, or transparently allowing the object to handle them. A *proxy* wraps another object and intercepts operations, like reading/writing properties and others, optionally handling them on its own, or transparently allowing the object to handle them.
@ -175,7 +174,7 @@ dictionary = new Proxy(dictionary, ...);
numbers = new Proxy(numbers, ...); numbers = new Proxy(numbers, ...);
``` ```
The proxy should totally replace the target object everywhere. No one should ever reference the target object after it got proxied. Otherwise it 's easy to mess up. The proxy should totally replace the target object everywhere. No one should ever reference the target object after it got proxied. Otherwise it's easy to mess up.
```` ````
## Validation with "set" trap ## Validation with "set" trap

View file

@ -22,7 +22,7 @@ function sayHi() {
alert("Hello"); alert("Hello");
} }
// global functions are methods of the global objecct: // global functions are methods of the global object:
window.sayHi(); window.sayHi();
``` ```