This commit is contained in:
Ilya Kantor 2019-06-20 16:16:45 +03:00
parent eeee9fedf7
commit 7697f95e24
4 changed files with 41 additions and 38 deletions

View file

@ -15,13 +15,13 @@ The error message in most browsers does not give understanding what went wrong.
**The error appears because a semicolon is missing after `user = {...}`.**
JavaScript does not assume a semicolon before a bracket `(user.go)()`, so it reads the code like:
JavaScript does not auto-insert a semicolon before a bracket `(user.go)()`, so it reads the code like:
```js no-beautify
let user = { go:... }(user.go)()
```
Then we can also see that such a joint expression is syntactically a call of the object `{ go: ... }` as a function with the argument `(user.go)`. And that also happens on the same line with `let user`, so the `user` object has not yet even been defined, hence the error.
Then we can also see that such a joint expression is syntactically a call of the object `{ go: ... }` as a function with the argument `(user.go)`. And that also happens on the same line with `let user`, so the `user` object has not yet even been defined, hence the error.
If we insert the semicolon, all is fine:
@ -35,9 +35,3 @@ let user = {
```
Please note that brackets around `(user.go)` do nothing here. Usually they setup the order of operations, but here the dot `.` works first anyway, so there's no effect. Only the semicolon thing matters.

View file

@ -14,11 +14,11 @@ let user = makeUser();
alert( user.ref.name ); // Error: Cannot read property 'name' of undefined
```
That's because rules that set `this` do not look at object literals.
That's because rules that set `this` do not look at object definition. Only the moment of call matters.
Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method.
Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method with "dot" syntax.
And the object literal itself has no effect on `this`. The value of `this` is one for the whole function, code blocks and object literals do not affect it.
The value of `this` is one for the whole function, code blocks and object literals do not affect it.
So `ref: this` actually takes current `this` of the function.
@ -42,5 +42,3 @@ alert( user.ref().name ); // John
```
Now it works, because `user.ref()` is a method. And the value of `this` is set to the object before dot `.`.

View file

@ -257,11 +257,11 @@ user.hi(); // John (the simple call works)
*/!*
```
On the last line there is a ternary operator that chooses either `user.hi` or `user.bye`. In this case the result is `user.hi`.
On the last line there is a conditinal operator that chooses either `user.hi` or `user.bye`. In this case the result is `user.hi`.
The method is immediately called with parentheses `()`. But it doesn't work right!
Then the method is immediately called with parentheses `()`. But it doesn't work right!
You can see that the call results in an error, because the value of `"this"` inside the call becomes `undefined`.
As you can see, the call results in an error, because the value of `"this"` inside the call becomes `undefined`.
This works (object dot method):
```js
@ -306,7 +306,7 @@ The Reference Type is a "specification type". We can't explicitly use it, but it
The value of Reference Type is a three-value combination `(base, name, strict)`, where:
- `base` is the object.
- `name` is the property.
- `name` is the property name.
- `strict` is true if `use strict` is in effect.
The result of a property access `user.hi` is not a function, but a value of Reference Type. For `user.hi` in strict mode it is:
@ -318,6 +318,8 @@ The result of a property access `user.hi` is not a function, but a value of Refe
When parentheses `()` are called on the Reference Type, they receive the full information about the object and its method, and can set the right `this` (`=user` in this case).
Reference type is a special "intermediary" internal type, with the purpose to pass information from dot `.` to calling parentheses `()`.
Any other operation like assignment `hi = user.hi` discards the reference type as a whole, takes the value of `user.hi` (a function) and passes it on. So any further operation "loses" `this`.
So, as the result, the value of `this` is only passed the right way if the function is called directly using a dot `obj.method()` or square brackets `obj['method']()` syntax (they do the same here). Later in this tutorial, we will learn various ways to solve this problem such as [func.bind()](/bind#solution-2-bind).