◐ Shell
reader mode source ↗
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
**Error**!

Try it:

```js run
let user = {
name: "John",
go: function() { alert(this.name) }
}

(user.go)() // error!
```

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 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.

If we insert the semicolon, all is fine:

```js run
let user = {
@@ -34,4 +34,4 @@ let user = {
(user.go)() // John
```

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.
21 changes: 10 additions & 11 deletions 1-js/04-object-basics/04-object-methods/3-why-this/solution.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@

Here's the explanations.

1. That's a regular object method call.

2. The same, brackets do not change the order of operations here, the dot is first anyway.

3. Here we have a more complex call `(expression).method()`. The call works as if it were split into two lines:

```js no-beautify
f = obj.go; // calculate the expression
f(); // call what we have
```

Here `f()` is executed as a function, without `this`.

4. The similar thing as `(3)`, to the left of the dot `.` we have an expression.

To explain the behavior of `(3)` and `(4)` we need to recall that property accessors (dot or square brackets) return a value of the Reference Type.

Any operation on it except a method call (like assignment `=` or `||`) turns it into an ordinary value, which does not carry the information allowing to set `this`.

7 changes: 3 additions & 4 deletions 1-js/04-object-basics/04-object-methods/3-why-this/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 3

---

# Explain the value of "this"

In the code below we intend to call `user.go()` method 4 times in a row.

But calls `(1)` and `(2)` works differently from `(3)` and `(4)`. Why?

```js run no-beautify
let obj, method;
Expand All @@ -23,4 +23,3 @@ obj.go(); // (1) [object Object]

(obj.go || obj.stop)(); // (4) undefined
```

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
**Answer: an error.**

Try it:
```js run
function makeUser() {
return {
Expand All @@ -11,18 +11,18 @@ function makeUser() {

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 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 with "dot" syntax.

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.

Here's the opposite case:

```js run
function makeUser() {
Expand All @@ -41,4 +41,4 @@ let user = makeUser();
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 `.`.
13 changes: 6 additions & 7 deletions 1-js/04-object-basics/04-object-methods/7-calculator/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ importance: 5

---

# Create a calculator

Create an object `calculator` with three methods:

- `read()` prompts for two values and saves them as object properties.
- `sum()` returns the sum of saved values.
- `mul()` multiplies saved values and returns the result.

```js
let calculator = {
// ... your code ...
};

calculator.read();
Expand All @@ -21,4 +21,3 @@ alert( calculator.mul() );
```

[demo]

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The solution is to return the object itself from every call.

```js run demo
let ladder = {
Expand Down Expand Up @@ -26,7 +26,7 @@ let ladder = {
ladder.up().up().down().up().down().showStep(); // 1
```

We also can write a single call per line. For long chains it's more readable:

```js
ladder
Expand Down
16 changes: 8 additions & 8 deletions 1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ importance: 2

---

# Chaining

There's a `ladder` object that allows to go up and down:

```js
let ladder = {
step: 0,
up() {
this.step++;
},
down() {
this.step--;
},
showStep: function() { // shows the current step
alert( this.step );
}
};
```

Now, if we need to make several calls in sequence, can do it like this:

```js
ladder.up();
Expand All @@ -30,10 +30,10 @@ ladder.down();
ladder.showStep(); // 1
```

Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this:

```js
ladder.up().up().down().showStep(); // 1
```

Such approach is widely used across JavaScript libraries.
Loading
Toggle all file notes Toggle all file annotations