This commit is contained in:
Ilya Kantor 2017-05-10 18:07:57 +03:00
commit d184bf8a98
21 changed files with 57 additions and 57 deletions

View file

@ -4,7 +4,7 @@ importance: 5
# Hello, object
Write the code, each line for an action:
Write the code, one line for each action:
1. Create an empty object `user`.
2. Add the property `name` with the value `John`.

View file

@ -35,7 +35,7 @@ let user = { // an object
};
```
A property has a key (also known as "name" and "identifier") before the colon `":"` and a value to the right of it.
A property has a key (also known as "name" or "identifier") before the colon `":"` and a value to the right of it.
In the `user` object, there are two properties:
@ -125,7 +125,7 @@ delete user["likes birds"];
Now everything is fine. Please note that the string inside the brackets is properly quoted (any type of quotes will do).
Square brackets are also provide a way to access a property by the name from the variable:
Square brackets also provide a way to obtain the property name as the result of any expression - as opposed to a litteral string - like from a variable as follows:
```js
let key = "likes birds";
@ -134,7 +134,7 @@ let key = "likes birds";
user[key] = true;
```
Here, the variable `key` may be calculated at run-time or depend on the user input. And then we use it to access the property. That gives us a great deal of flexibility. The dot notation cannot be used in similar way.
Here, the variable `key` may be calculated at run-time or depend on the user input. And then we use it to access the property. That gives us a great deal of flexibility. The dot notation cannot be used in a similar way.
For instance:
@ -270,7 +270,7 @@ let user = {
};
```
## Existance check
## Existence check
A notable objects feature is that it's possible to access any property. There will be no error if the property doesn't exist! Accessing a non-existing property just returns `undefined`. It provides a very common way to test whether the property exists -- to get it and compare vs undefined:
@ -296,7 +296,7 @@ alert( "age" in user ); // true, user.age exists
alert( "blabla" in user ); // false, user.blabla doesn't exist
```
Please note that at the left side of `in` there must be a *property name*. That's usually a quoted string.
Please note that on the left side of `in` there must be a *property name*. That's usually a quoted string.
If we omit quotes, that would mean a variable containing the actual name to be tested. For instance:
@ -698,7 +698,7 @@ alert(clone.sizes.width); // 51, see the result from the other one
To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate it's structure as well. That is called a "deep cloning".
There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](https://w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). Not to reinvent the wheel, we can use a working implementation of it from the JavaScript library [lodash](https://lodash.com), the method is called [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep).
There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](https://w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). In order not to reinvent the wheel, we can use a working implementation of it from the JavaScript library [lodash](https://lodash.com), the method is called [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep).

View file

@ -117,9 +117,9 @@ delete family.mother.husband;
![](family-delete-refs.png)
It's not enough to delete any one of them, because all objects would still be reachable.
It's not enough to delete only one of these two references, because all objects would still be reachable.
But if we delete both, then we can see that John has no incoming references any more:
But if we delete both, then we can see that John has no incoming reference any more:
![](family-no-father.png)

View file

@ -158,7 +158,7 @@ For instance, different parts of our application want to access symbol `"id"` me
To achieve that, there exists a *global symbol registry*. We can create symbols in it and and access them later, and it guarantees that repeated accesses by the same name return exactly the same symbol.
To can create or read a symbol in the registry, use `Symbol.for(name)`.
In order to create or read a symbol in the registry, use `Symbol.for(name)`.
For instance:

View file

@ -221,11 +221,11 @@ In non-strict mode (if one forgets `use strict`) the value of `this` in such cas
Please note that usually a call of a function that uses `this` without an object is not normal, but rather a programming mistake. If a function has `this`, then it is usually meant to be called in the context of an object.
```smart header="The consequences of unbound `this`"
If you come from another programming languages, then you are probably used to an idea of a "bound `this`", where methods defined in an object always have `this` referencing that object.
If you come from another programming language, then you are probably used to the idea of a "bound `this`", where methods defined in an object always have `this` referencing that object.
In JavaScript `this` is "free", its value is evaluated at the call time and depends not on where the method was declared, but rather on what's the object "before dot".
In JavaScript `this` is "free", its value is evaluated at call-time and does not depend on where the method was declared, but rather on what's the object "before the dot".
The concept of run-time evaluated `this` has both pluses and minuses. From one side, a function can be reused for different objects. From the other side, greater flexibility opens a place for mistakes.
The concept of run-time evaluated `this` has both pluses and minuses. On the one hand, a function can be reused for different objects. On the the other hand, greater flexibility opens a place for mistakes.
Here our position is not to judge whether this language design decision is good or bad. We'll understand how to work with it, how to get benefits and evade problems.
```
@ -238,7 +238,7 @@ This section covers an advanced topic, to understand certain edge-cases better.
If you want to go on faster, it can be skipped or postponed.
```
An intricate method call can loose `this`, for instance:
An intricate method call can lose `this`, for instance:
```js run
let user = {
@ -322,7 +322,7 @@ So, as the result, the value of `this` is only passed the right way if the funct
## Arrow functions have no "this"
Arrow functions are special: they don't have "own" `this`. If we reference `this` from such function, it's taken from the outer "normal" function.
Arrow functions are special: they don't have their "own" `this`. If we reference `this` from such a function, it's taken from the outer "normal" function.
For instance, here `arrow()` uses `this` from the outer `user.sayHi()` method:

View file

@ -87,7 +87,7 @@ The constructor can't be called again, because it is not saved anywhere, just cr
## Dual-use constructors: new.target
Inside a function, we can check how it is called with `new` or without it, using a special `new.target` property.
Inside a function, we can check whether it was called with `new` or without it, using a special `new.target` property.
It is empty for ordinary runs and equals the function if called with `new`:
@ -116,7 +116,7 @@ let john = User("John"); // redirects call to new User
alert(john.name); // John
```
This approach is sometimes used in libraries to make the syntax more flexible. Probably not a good thing to use everywhere though, because it makes a bit less obvious what's going on for a person who's familiar with internals of `User`.
This approach is sometimes used in libraries to make the syntax more flexible. Probably not a good thing to use everywhere though, because it makes a bit less obvious what's going on for a person who's familiar with the internals of `User`.
## Return from constructors
@ -158,7 +158,7 @@ function SmallUser() {
alert( new SmallUser().name ); // John
```
Most of time constructors return nothing. Here we mention the special behavior with returning objects mainly for the sake of completeness.
Most of the time constructors return nothing. Here we mention the special behavior with returning objects mainly for the sake of completeness.
````smart header="Omitting brackets"
By the way, we can omit brackets after `new`, if it has no arguments:
@ -208,7 +208,7 @@ john = {
- Constructor functions or, shortly, constructors, are regular functions, but there's a common agreement to name them with capital letter first.
- Constructor functions should only be called using `new`. Such call implies a creation of empty `this` at the start and returning the populated one at the end.
We can use constructor functions to make multiple similar objects. But the topic is much deeper than described here. So we'll return it later and cover more in-depth.
We can use constructor functions to make multiple similar objects. But the topic is much deeper than described here. So we'll return to it later and cover it more in-depth.
JavaScript provides constructor functions for many built-in language objects: like `Date` for dates, `Set` for sets and others that we plan to study.