Skip to content

Commit afd9f18

Browse files
committed
add another example and convert unix format.
Signed-off-by: Bo-Yi Wu <[email protected]>
1 parent 7073dfa commit afd9f18

File tree

1 file changed

+85
-79
lines changed

1 file changed

+85
-79
lines changed

doc/zhtw/function/closures.md

Lines changed: 85 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,85 @@
1-
## Closures 和 References
2-
3-
JavaScript 有一個很重要的特徵就是 **closures**
4-
因為有 Closures,所以作用域 **永遠** 能夠去訪問作用區間外面的變數。
5-
[函數區間](#function.scopes) 是JavaScript 中唯一擁有自生作用域的結構,因此 Closures 的創立需要依賴函數
6-
7-
### 模仿私有變數
8-
9-
function Counter(start) {
10-
var count = start;
11-
return {
12-
increment: function() {
13-
count++;
14-
},
15-
16-
get: function() {
17-
return count;
18-
}
19-
}
20-
}
21-
22-
var foo = Counter(4);
23-
foo.increment();
24-
foo.get(); // 5
25-
26-
這裡,`Counter` 返回兩個 Closures,函數 `increment` 還有 `get`。這兩個函數都維持著對外部作用域 `Counter` 的引用,因此總可以訪問作用域的變數 `count`
27-
28-
29-
### 為什麼不可以在外部訪問私有變數
30-
31-
因為 Javascript **不可以** 對作用域進行引用或賦值。因此外部的地方沒有辦法訪問 `count` 變數。
32-
唯一的途徑就是經過那兩個 Closures
33-
34-
var foo = new Counter(4);
35-
foo.hack = function() {
36-
count = 1337;
37-
};
38-
39-
在上面的例子中 `count` **不會** 改變到 `Counter` 裡面的 `count` 的值。因為 `foo.hack` 沒有在 **那個** 作用域內被宣告。它只有會覆蓋或者建立在一個 **全域** 的變數 `count`
40-
41-
### 在循環內的 Closures
42-
43-
一個常見的錯誤就是在 Closures 中使用迴圈,假設我們要使用每次迴圈中所使用的進入變數
44-
45-
for(var i = 0; i < 10; i++) {
46-
setTimeout(function() {
47-
console.log(i);
48-
}, 1000);
49-
}
50-
51-
在上面的例子中它 **不會** 輸出數字從 `0``9`,但只會出現數字 `10` 十次。
52-
`console.log` 被呼叫的時候,這個 *匿名* 函數中保持一個 **參考** 到 i ,此時 `for`迴圈已經結束, `i` 的值被修改成了 `10`
53-
為了要達到想要的結果,需要在每次創造 **副本** 來儲存 `i` 的變數。
54-
55-
### 避免引用錯誤
56-
57-
為了要有達到正確的效果,最好是把它包在一個
58-
[匿名函數](#function.scopes).
59-
60-
for(var i = 0; i < 10; i++) {
61-
(function(e) {
62-
setTimeout(function() {
63-
console.log(e);
64-
}, 1000);
65-
})(i);
66-
}
67-
68-
匿名外部的函數被呼叫,並把 `i` 作為它第一個參數,此時函數內 `e` 變數就擁有了一個 `i` 的拷貝。
69-
當傳遞給 `setTimeout` 這個匿名函數執行時,它就擁有了對 `e` 的引用,而這個值 **不會** 被循環改變。
70-
另外有一個方法也可以完成這樣的工作,那就是在匿名函數中返回一個函數,這和上面的程式碼有同樣的效果。
71-
72-
for(var i = 0; i < 10; i++) {
73-
setTimeout((function(e) {
74-
return function() {
75-
console.log(e);
76-
}
77-
})(i), 1000)
78-
}
79-
1+
## Closures 和 References
2+
3+
JavaScript 有一個很重要的特徵就是 **closures**
4+
因為有 Closures,所以作用域 **永遠** 能夠去訪問作用區間外面的變數。
5+
[函數區間](#function.scopes) 是JavaScript 中唯一擁有自生作用域的結構,因此 Closures 的創立需要依賴函數
6+
7+
### 模仿私有變數
8+
9+
function Counter(start) {
10+
var count = start;
11+
return {
12+
increment: function() {
13+
count++;
14+
},
15+
16+
get: function() {
17+
return count;
18+
}
19+
}
20+
}
21+
22+
var foo = Counter(4);
23+
foo.increment();
24+
foo.get(); // 5
25+
26+
這裡,`Counter` 返回兩個 Closures,函數 `increment` 還有 `get`。這兩個函數都維持著對外部作用域 `Counter` 的引用,因此總可以訪問作用域的變數 `count`
27+
28+
29+
### 為什麼不可以在外部訪問私有變數
30+
31+
因為 Javascript **不可以** 對作用域進行引用或賦值。因此外部的地方沒有辦法訪問 `count` 變數。
32+
唯一的途徑就是經過那兩個 Closures
33+
34+
var foo = new Counter(4);
35+
foo.hack = function() {
36+
count = 1337;
37+
};
38+
39+
在上面的例子中 `count` **不會** 改變到 `Counter` 裡面的 `count` 的值。因為 `foo.hack` 沒有在 **那個** 作用域內被宣告。它只有會覆蓋或者建立在一個 **全域** 的變數 `count`
40+
41+
### 在循環內的 Closures
42+
43+
一個常見的錯誤就是在 Closures 中使用迴圈,假設我們要使用每次迴圈中所使用的進入變數
44+
45+
for(var i = 0; i < 10; i++) {
46+
setTimeout(function() {
47+
console.log(i);
48+
}, 1000);
49+
}
50+
51+
在上面的例子中它 **不會** 輸出數字從 `0``9`,但只會出現數字 `10` 十次。
52+
`console.log` 被呼叫的時候,這個 *匿名* 函數中保持一個 **參考** 到 i ,此時 `for`迴圈已經結束, `i` 的值被修改成了 `10`
53+
為了要達到想要的結果,需要在每次創造 **副本** 來儲存 `i` 的變數。
54+
55+
### 避免引用錯誤
56+
57+
為了要有達到正確的效果,最好是把它包在一個
58+
[匿名函數](#function.scopes).
59+
60+
for(var i = 0; i < 10; i++) {
61+
(function(e) {
62+
setTimeout(function() {
63+
console.log(e);
64+
}, 1000);
65+
})(i);
66+
}
67+
68+
匿名外部的函數被呼叫,並把 `i` 作為它第一個參數,此時函數內 `e` 變數就擁有了一個 `i` 的拷貝。
69+
當傳遞給 `setTimeout` 這個匿名函數執行時,它就擁有了對 `e` 的引用,而這個值 **不會** 被循環改變。
70+
另外有一個方法也可以完成這樣的工作,那就是在匿名函數中返回一個函數,這和上面的程式碼有同樣的效果。
71+
72+
for(var i = 0; i < 10; i++) {
73+
setTimeout((function(e) {
74+
return function() {
75+
console.log(e);
76+
}
77+
})(i), 1000)
78+
}
79+
80+
另外也可以透過 `.bind` 完成此工作,它可以將 `this` 及參數傳入函數內,行為就如同上面程式碼一樣。
81+
82+
for(var i = 0; i < 10; i++) {
83+
setTimeout(console.log.bind(console, i), 1000);
84+
}
85+

0 commit comments

Comments
 (0)