Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object methods, "this" #56

Merged
merged 5 commits into from
Oct 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions 1-js/04-object-basics/04-object-methods/2-check-syntax/solution.md
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!
(user.go)() // 錯誤!
```

The error message in most browsers does not give understanding what went wrong.
大多數瀏覽器的錯誤訊息不會說明是什麼出錯。

**The error appears because a semicolon is missing after `user = {...}`.**
**該錯誤出現是因為,在 `user = {...}` 之後少了個分號。**

JavaScript does not auto-insert a semicolon before a bracket `(user.go)()`, so it reads the code like:
JavaScript 不會在 `(user.go)()` 前面自動插入分號,所以這段程式碼它看起來像這樣:

```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.
然後我們也可以看到這種結合的表達式,依照語法將物件 `{ go: ... }` 視為函式,並使用引數 `(user.go)` 來呼叫。且同樣的情況發生在同一行的 `let user` 上,而 `user` 物件根本還沒完成定義,進而產生錯誤。

If we insert the semicolon, all is fine:
若我們加入一個分號,就都沒問題了:

```js run
let user = {
Expand All @@ -34,4 +34,5 @@ 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.
請注意在圍繞著 `(user.go)` 的括號在這時根本沒作用。通常它們用在設定操作的順序,但此處的句點 `.` 無論如何都會先運行,所以沒效果。只有分號這件事較重要。

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ importance: 2

---

# Syntax check

What is the result of this code?
# 語法確認

底下程式碼執行的結果為何?

```js no-beautify
let user = {
Expand All @@ -16,4 +15,5 @@ let user = {
(user.go)()
```

P.S. There's a pitfall :)
註:有個小陷阱 :)

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. 這是正規的物件方法呼叫。

1. That's a regular object method call.
2. 同樣地,括號在此不變更操作順序,句點無論如何都會先執行。

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:
3. 此處我們有個更為複雜的呼叫 `(expression).method()`。這個呼叫就像被拆成兩行一樣:

```js no-beautify
f = obj.go; // calculate the expression
f(); // call what we have
f = obj.go; // 計算表達式
f(); // 呼叫擁有的東西
```

Here `f()` is executed as a function, without `this`.
此處 `f()` 被視為函式執行,且不帶有 `this`

4. The similar thing as `(3)`, to the left of the dot `.` we have an expression.
4. `(3)` 是類似的事情,在句點 `.` 左側我們有個表達式。

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.
要解釋 `(3)` `(4)` 的行為,我們需要回想屬性存取運算子(句點或方括號)回傳的是參考類型的值。

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`.
任何除了方法呼叫以外的任意操作(像是指定 `=` `||`) 都會把它轉為不能設定 `this` 資訊的一般值。

6 changes: 3 additions & 3 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"
# 解釋 "this" 的值

In the code below we intend to call `user.go()` method 4 times in a row.
底下的程式碼我們試圖連續呼叫四次 `user.go()` 方法。

But calls `(1)` and `(2)` works differently from `(3)` and `(4)`. Why?
然而呼叫 `(1)` `(2)` 運作起來與 `(3)` `(4)` 有所不同,為什麼?

```js run no-beautify
let obj, method;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
**Answer: an error.**
**答案:一個錯誤。**

試試看:

Try it:
```js run
function makeUser() {
return {
Expand All @@ -14,15 +15,15 @@ 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.
這是因為設定 `this` 的規則並不看物件定義,只有呼叫那一刻才是重要的。

Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method with "dot" syntax.
此處在 `makeUser()` 中 `this` 的值是 `undefined`,因為它被視為一個函式來呼叫,而不是使用 "句點" 語法呼叫的一個方法。

The value of `this` is one for the whole function, code blocks and object literals do not affect it.
`this` 的值是對於整個函式而言的,程式碼區塊跟物件字面值皆不會影響它。

So `ref: this` actually takes current `this` of the function.
因此 `ref: this` 實際上拿到當前函式的 `this`

Here's the opposite case:
這邊有個相反的情況:

```js run
function makeUser() {
Expand All @@ -41,4 +42,5 @@ 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 `.`.
現在它可以正常運作了,因為 `user.ref()` 是個方法,且 `this` 的值被設定為在句點 `.` 之前的那個物件。

Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Using "this" in object literal
# 在物件字面值上使用 "this"

Here the function `makeUser` returns an object.
這個函式 `makeUser` 回傳一個物件。

What is the result of accessing its `ref`? Why?
存取它的 `ref` 會得到什麼結果呢?為什麼?

```js
function makeUser() {
Expand All @@ -18,6 +18,6 @@ function makeUser() {

let user = makeUser();

alert( user.ref.name ); // What's the result?
alert( user.ref.name ); // 結果是什麼?
```

12 changes: 6 additions & 6 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:
建立一個物件 `calculator` 並有三個方法在內:

- `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.
- `read()` 提示輸入(prompt)兩個值並將它們儲存到物件屬性內。
- `sum()` 回傳儲存值的總和。
- `mul()` 相乘儲存的值並回傳結果。

```js
let calculator = {
// ... your code ...
// ... 你的程式碼 ...
};

calculator.read();
Expand Down
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 All @@ -37,3 +37,4 @@ ladder
.down()
.showStep(); // 1
```

13 changes: 7 additions & 6 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,9 +2,9 @@ importance: 2

---

# Chaining
# 鏈接呼叫(Chaining

There's a `ladder` object that allows to go up and down:
有個 `ladder` 物件允許向上或向下:

```js
let ladder = {
Expand All @@ -15,13 +15,13 @@ let ladder = {
down() {
this.step--;
},
showStep: function() { // shows the current step
showStep: function() { // 顯示目前階梯
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,11 @@ ladder.down();
ladder.showStep(); // 1
```

Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this:
修改 `up``down` `showStep` 的程式碼以使得呼叫為鏈接方式,像這樣:

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

Such approach is widely used across JavaScript libraries.
這種作法在 JavaScript 函式庫內被廣泛地使用著。

Loading