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

week17Hw OK #26

Merged
merged 1 commit into from
Sep 20, 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
32 changes: 32 additions & 0 deletions homeworks/week17/hw1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
``` js
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
console.log(3)
setTimeout(() => {
console.log(4)
}, 0)
console.log(5)
```

``` output
1
3
5
2
4
```

``` 執行過程
1.`console.log(1)` 進入 Call Stack 直接執行,印出 1 後從 Call Stack pop
2.`setTimeout(() => { console.log(2) }, 0)` 進入 Call Stack 看到是 setTimeout 把 setTimeout 放到 WebApi 並設置計時器給它,經過 0 秒後會把 `console.log(2)` 放到 callback queue。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其實是把 () => { console.log(2) } 放到 callback queue

3.`console.log(3)` 進入 Call Stack 直接執行,印出 3 後從 Call Stack pop
4.`setTimeout(() => { console.log(4) }, 0)` 進入 Call Stack 看到是 setTimeout 把 setTimeout 放到 WebApi 並設置計時器給它,經過 0 秒後會把 `console.log(4)` 放到 callback queue。
5.`console.log(5)` 進入 Call Stack 直接執行,印出 5 後從 Call Stack pop
6.確認 Call Stack 沒東西後,檢查 Callback Queue 把`console.log(2)`,放到 Call Stack
7.執行 `console.log(2)`,印出 2 後從 Call Stack pop
8.從 Callback Queue 把`console.log(4)`,放到 Call Stack
9.執行 `console.log(4)`,印出 4 後從 Call Stack pop
10.程式結束
```
49 changes: 49 additions & 0 deletions homeworks/week17/hw2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
``` js
for(var i=0; i<5; i++) {
console.log('i: ' + i)
setTimeout(() => {
console.log(i)
}, i * 1000)
}
```

``` output
i: 0
i: 1
i: 2
i: 3
i: 4
5
5
5
5
5
```

``` 執行過程
1.給 i 值為 0 進入迴圈
- 第一圈迴圈
2.`console.log('i: ' + 0)` 進入 Call Stack 直接執行,印出 `i: 0` 後從 Call Stack pop
3.`setTimeout(() => { console.log(i) }, i * 1000)` 進入 Call Stack 看到是 setTimeout,把 setTimeout 放到 WebApi 並設置計時器,經過 0 秒後會放到 Callback Queue
4.執行 i++ ,i = 1
- 第二圈迴圈
5.`console.log('i: ' + 1)` 進入 Call Stack 直接執行,印出 `i: 1` 後從 Call Stack pop
6.`setTimeout(() => { console.log(i) }, i * 1000)` 進入 Call Stack 看到是 setTimeout,把 setTimeout 放到 WebApi 並設置計時器,經過 1 秒後會放到 Callback Queue
7.執行 i++ , i = 2
- 第三圈迴圈
8.`console.log('i: ' + 2)` 進入 Call Stack 直接執行,印出 `i: 2` 後從 Call Stack pop
9.`setTimeout(() => { console.log(i) }, i * 1000)` 進入 Call Stack 看到是 setTimeout,把 setTimeout 放到 WebApi 並設置計時器,經過 2 秒後會放到 Callback Queue
10.執行 i++, i = 3
- 第四圈迴圈
11.`console.log('i: ' + 3)` 進入 Call Stack 直接執行,印出 `i: 3` 後從 Call Stack pop
12.`setTimeout(() => { console.log(i) }, i * 1000)` 進入 Call Stack 看到是 setTimeout,把 setTimeout 放到 WebApi 並設置計時器,經過 3 秒後會放到 Callback Queue
13.執行 i++,i = 4
- 第五圈迴圈
14.`console.log('i: ' + 4)` 進入 Call Stack 直接執行,印出 `i: 4` 後從 Call Stack pop
15.`setTimeout(() => { console.log(i) }, i * 1000)` 進入 Call Stack 看到是 setTimeout,把 setTimeout 放到 WebApi 並設置計時器,經過 4 秒後會放到 Callback Queue
16.執行 i++,i = 5
17.因為 i = 5 不符合 i < 5 所以跳出迴圈。
18.確認 Call Stack 沒東西後,檢查 Callback Queue 把`console.log(i)`,放到 Call Stack(此時 i = 5)。
19.執行 `console.log(5)` 印出 5 後從 Call stack pop
20.重複 18.19 步驟直到 Call back queue 沒東西。
21.程式結束
153 changes: 153 additions & 0 deletions homeworks/week17/hw3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
``` js
var a = 1
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
b = 100
}
}
fn()
console.log(a)
a = 10
console.log(a)
console.log(b)
```

``` output
undefined
5
6
20
1
10
100
``` output

- Global EC 編譯
1. 進入 Global EC 並且初始化 VO 以及 scope chain

```
globalEC {
VO{
a: undefined
fn: function
},
scopeChain: [globalEC.VO]
}
```

- Global EC 執行
2. 執行 Global EC 將 a 設為 1,之後看到 fn() 把 fn() 放到 Call Stack 進入 fn EC 編譯

```
globalEC {
VO{
a: 1
fn: function
},
scopeChain: [globalEC.VO]
}
fn.[[scope]] = globalEC.scopeChain
```

- fnEC 編譯
3. 進入 fn EC 並且初始化 AO 以及 scope chain

```
fnEC {
AO {
a: undefined
fn2:function
},
scopeChain:[fn.AO]+fn.[[scope]]
}

globalEC {
VO {
a: 1
fn: function
},
scopeChain: [globalEC.VO]
}
fn.[[scope]] = globalEC.scopeChain
```

- fnEC 執行
4. 執行 fnEC 將 `console.log(a)` 放到 Call stack ,此時 a 的值會先找 fnEC.AO 找到 undefined 印出,印出後從 Call stack pop 掉
5.`var a = 5` 把 a 值設為 5
6.把 `console.log(5)` 放到 Call stack,印出 5 後 pop 掉
7.a++ , a = 6
8.`var a` 設定參數 a ,發現 fnEC.AO 已有 a ,所以不做事
9.進入 fn2EC 並且初始化 AO 以及 scope chain

```
fnEC {
AO {
a: 6
fn2:function
},
scopeChain:[fn.AO]+fn.[[scope]]
}
}


globalEC {
VO {
a: 1
fn: function
},
scopeChain: [globalEC.VO]
}

fn2.[[scope]] = fnEC.scopeChain = [fnEC.AO,globalEC.VO]
```

- fn2EC 編譯
10.進入 fn2EC 並且初始化 AO 以及 scope chain(這邊 AO 沒有東西就不多寫了)

- fn2EC 執行
11.執行 fn2EC 將 `console.log(a)` 放到 Call stack,這邊在 fn2EC.AO 找不到 a 就透過 scope chain 往上一層找,在 fnEC.VO 找到 a 的值為 6,印出 6 後從 Call stack 中 pop 掉
12.`a = 20`把 fnEC.VO 的 a 設為 20`
13.`b = 100` fn2EC.AO 找不到 b 往上一層找,fnEC.AO 也找不到 b ,再往上到 globalEC.VO 找還是找不到,因為再往上就是 null ,js 會自動在 globalEC.VO 裡宣告一個 b 並給值 100,fn2EC 結束。

```
fn2EC: {
AO: {
},
scopeChain: [fn2EC.AO fnEC.AO global.VO]
}
fnEC: {
AO: {
a: 20,
fn2: function
},
scopeChain: [fnEC.AO global.VO]
}
globalEC: {
VO: {
a: 1,
b: 100,
fn: function
},
scopeChain: [global.VO]
}
```

- 接續 fnEC 執行
14.`console.log(a)` 到 fnEC.AO 找 a 的值為 20,將 `console.log(20)` 放到 Call stack ,印出 20 後從 Call stack 中 pop 掉。
15.fnEC() 結束從 Call stack 中 pop 掉

- 接續 globalEC 執行
16.`console.log(a)` 到 globalEC.VO 找 a 的值為 1,將 `console.log(1)` 放到 Call stack ,印出 1 後從 Call stack 中 pop 掉。
17. `a = 10` 到 globalEC.VO 把 a 的值設為 10
18.`console.log(a)` 到 globalEC.VO 找 a 的值為 10,將 `console.log(10)` 放到 Call stack ,印出 10 後從 Call stack 中 pop 掉。
19.`console.log(b)`,到 globalEC.VO 找 b 的值為 100,將 `console.log(10)` 放到 Call stack ,印出 100 後從 Call stack 中 pop 掉。
20.globalEC 執行結束,從 Call stack 中 pop 掉。
37 changes: 37 additions & 0 deletions homeworks/week17/hw4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
``` js
const obj = {
value: 1,
hello: function() {
console.log(this.value)
},
inner: {
value: 2,
hello: function() {
console.log(this.value)
}
}
}

const obj2 = obj.inner
const hello = obj.inner.hello
obj.inner.hello() // ??
obj2.hello() // ??
hello() // ??
```

``` output
2
2
undefined
```

`obj.inner.hello()`
上面這個是語法糖的形式,實際上要使用 function 應該是 function call 這個形式,所以我們可以把這段程式碼轉成 `obj.inner.hello.call(obj.inner)`,call 裡面代的值就是 hello 這個 function 前的值,同時這個值就是 this。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

跟語法糖其實沒關係,我只是說 this 可以用這種形式來「代換」,但不等同於這是語法糖

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我是看this 的值到底是什么?一次说清楚 裡面有一段提到:

从看到这篇文章起,你一定要记住,第三种调用形式,才是正常调用形式:

func.call(context, p1, p2)

其他两种都是语法糖,可以等价地变为 call 形式:

func(p1, p2) 等价于
func.call(undefined, p1, p2)

obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)

请记下来。(我们称此代码为「转换代码」,方便下文引用)

至此我们的函数调用只有一种形式:

func.call(context, p1, p2)

裡面提到這其他兩種都是語法糖才這樣寫的

看到老師回答後,我去找了一下維基對語法糖的定義

語法糖,指電腦語言中添加的某種語法,這種語法對語言的功能沒有影響,但是更方便程式設計師使用。

以這段定義來說,純 function 沒辦法改變 this 的值,所以這樣不算語法糖只是可以代換,不知道這樣對不對?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原來是文章裡面提到的,我自己是對這說法保持懷疑啦
因為要證明 JS 底層真的是轉成這種形式才能說是語法糖


所以這邊 this 就等於 obj.inner = 2

`obj2.hello()`
一樣的方法轉換為`obj2.hello.call(obj2)`,obj2 = obj.inner = 2,這邊 this 的值也是 2

`hello()`
轉為 `hello.call()` 由於括號內沒值,所以 this 為 undefined。
5 changes: 5 additions & 0 deletions homeworks/week17/hw5.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
## 這週學了一大堆以前搞不懂的東西,你有變得更懂了嗎?請寫下你的心得。

一開始看 prototype 想說前面滿簡單的,直到我看到了 instanceof 裡的 Function 和 Object 互為彼此的 instance,整個思路直接卡死在裡面出不來,尤其是 `Function.__proto__ === Function.prototype` 這句,後來重新看了好幾次+自己寫程式碼重複驗證才有比較清楚(寫 code 重複驗證自己思路真的很有用印象也比較深)

另一個難題應該是 this 了,一開始看完 What's THIS in JavaScript? 覺得 this 也沒什麼,信心滿滿的接續看了老師的文章後馬上傻眼XD,範例只答的出一個馬上被打臉,後來也是一篇文章重複看了好幾遍,然後某天就突然通了, call 的方法懂了後真的簡單好用。

第一次好好的理解程式語言的底層到底在幹嘛,看了老師的文章真的有了解滿多不同的東西,那個大安 star 的 code 實做出來我有嚇到XD,繼續邁進下一週。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那個大安 star 的 code 實做出來我有嚇到

這是什麼?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

所有的函式都是閉包:談 JS 中的作用域與 Closure全域變數就是國際巨星這段,直接把說法轉成程式碼覺得很厲害XD

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

喔喔,我自己都忘記這一段了XDD