-
Notifications
You must be signed in to change notification settings - Fork 0
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
week17Hw OK #26
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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。 | ||
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.程式結束 | ||
``` |
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.程式結束 |
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 掉。 |
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。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 跟語法糖其實沒關係,我只是說 this 可以用這種形式來「代換」,但不等同於這是語法糖 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 我是看this 的值到底是什么?一次说清楚 裡面有一段提到:
func.call(context, p1, p2)
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 的值,所以這樣不算語法糖只是可以代換,不知道這樣對不對? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 原來是文章裡面提到的,我自己是對這說法保持懷疑啦 |
||
|
||
所以這邊 this 就等於 obj.inner = 2 | ||
|
||
`obj2.hello()` | ||
一樣的方法轉換為`obj2.hello.call(obj2)`,obj2 = obj.inner = 2,這邊 this 的值也是 2 | ||
|
||
`hello()` | ||
轉為 `hello.call()` 由於括號內沒值,所以 this 為 undefined。 |
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,繼續邁進下一週。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
這是什麼? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 所有的函式都是閉包:談 JS 中的作用域與 Closure全域變數就是國際巨星這段,直接把說法轉成程式碼覺得很厲害XD There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 喔喔,我自己都忘記這一段了XDD |
There was a problem hiding this comment.
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