📓
📓
📓
📓
Something About JavaScript
Search…
📓
📓
📓
📓
Something About JavaScript
Introduction
Day 1:前言
Day 2:資料型態的夢魘——動態型別加弱型別(1)
Day 3:資料型態的夢魘——動態型別加弱型別(2)
Day 4:動態型別加弱型別不是罪——怎麼 JavaScript 一摔就變成個印度阿三?
Day 5:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (1)
Day 6:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (2)
Day 7:傳統 var 關鍵字的不足
Day 8:var 掰掰 —— ES6 更嚴謹安全的 let 和 const
Day 9:圖解變數作用域(Scope)
Day 10:程式也懂電梯向上? —— Hoisting
Day 11:Strict Mode (嚴謹模式)
Day 12:看 Strict Mode 如何施展「還我漂亮拳」(1)
Day 13:看 Strict Mode 如何施展「還我漂亮拳」(2)
Day 14:來挖挖恐龍骨 —— with 語法
Day 15:this 關鍵字 (1)
Day 16:this 關鍵字 (2)
Day 17:this 關鍵字 (3)
Day 18:this 關鍵字 (4)
Day 19:函數定義 (Function Definition) 的 100 種寫法
Day 20:ES6 的箭頭函數 (Arrow Functions)
Day 21:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (1)
Day 22:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (2)
Day 23:ES6 物件實字威力加強版 (Enhanced Object Literals)
Day 24:函數呼叫 (Function Invocation) 與立即函數 (Self-Invoking Functions)
Day 25:不是多了塊魚 —— 立即函數的應用整理
Day 26:程式界的哈姆雷特 —— Pass by value, or Pass by reference?
Day 27:別管變數 Pass by Whatever,尋找容易理解的銀色子彈 (Silver Bullet)
Day 28:閉包 (Closures)
Day 29:閉包 (Closures) 進階打怪實戰
Day 30:ES10 醞釀中 —— 擁抱 JS の 未來
Powered By
GitBook
Day 25:不是多了塊魚 —— 立即函數的應用整理
上一篇介紹到立即函數 (Self-Invoking Functions) 的用法,過程有沒有產生一個疑惑?
例如大費周章包裝了一個立即函數:
1
(
function
()
{
2
console
.
log
(
'Hello'
);
3
})();
Copied!
不如直接執行還比較乾脆:
1
console
.
log
(
'Hello'
);
Copied!
一樣都是立刻執行的效果,何必脫褲子放屁,多此一舉,豈非多餘?
(Source:
Youtube
)
立即函數是脫褲子放屁?
程式是工具,工具是為了幫助解決問題而存在才有意義,不會單純因為語法酷炫或用起來很潮而增加價值。
一開始學到立即函數時,我的第一個感想確實是覺得很多餘。
但我相信每個語法的存在一定有其用意,因此試著去觀摩和整理使用立即函數的場合。
以下是我目前歸納出的用途,歡迎補充:
用途 1:封裝一次性的 Local Scope
可以封裝一段想立刻執行的程式碼,建立一次性的 Local Scope,讓一次性變數的生命週期留在函數內,避免汙染到 Global Scope。
Before:
在未經封裝前,一次性用途的變數
temp
暴露在全域作用域下,潛藏後續對其他程式造成干擾的風險:
1
var
temp
=
10
+
5
;
2
console
.
log
(
"Answer is "
+
temp
);
3
4
// 執行其他的任務
5
otherMission
();
6
function
otherMission
(){
7
console
.
log
(
temp
);
// temp 是全域變數,仍然存在
8
}
Copied!
執行結果:
1
Answer is 15
2
15
Copied!
After:
透過立即函數作封裝,避免不必要的變數影響殘留:
1
(
function
(){
2
var
temp
=
10
+
5
;
3
console
.
log
(
"Answer is "
+
temp
);
4
})();
5
6
// 執行其他的任務
7
otherMission
();
8
function
otherMission
(){
9
console
.
log
(
temp
);
// temp 不存在於此作用域
10
}
Copied!
執行結果:
1
Answer is 15
2
Uncaught ReferenceError: temp is not defined
Copied!
自然,也可以用普通的函數包裝,再透過函數呼叫來執行,差別是還要為函數作命名:
1
function execOneTime(){
2
var temp = 10 + 5;
3
console.log("Answer is " + temp);
4
}
5
execOneTime();
6
7
// 執行其他的任務
8
otherMission();
9
function otherMission(){
10
console.log(temp); // temp 不存在於此作用域
11
}
Copied!
好的命名也是需要花腦細胞去想,既然只是一次性而且立即性的用途,那就用立即函數吧!
用途 2:為物件實字 (Object Literals) 的屬性初始值產生動態值
Before:
原本如果想為物件屬性產生動態數值,必須先產生基本的初始物件,再額外對屬性來動態賦值:
1
var
student
=
{};
2
student
.
score
=
Math
.
random
();
3
console
.
log
(
student
.
score
);
// 0.7779381225655557
Copied!
After:
透過立即函數的用法,可以在物件實字初始化階段就動態產生結果:
1
var
student
=
{
2
score
:
(
function
(){
return
Math
.
random
();
})()
3
};
4
console
.
log
(
student
.
score
);
// 0.7779381225655557
Copied!
用途 3:將字串內容轉成函數物件
資料傳遞格式 JSON 不支援儲存函數型態的資料,理論上無法用來傳遞函數物件。
但透過立即函數,配合
eval()
,就有機會實現用 JSON 傳遞函數型態資料,例如以下範例:
1
var
text
=
'{ "name":"John", "age":"function () {return 30;}"}'
;
2
var
person
=
JSON
.
parse
(
text
);
3
4
console
.
log
(
person
);
// {name: "John", age: "function () {return 30;}"}
5
console
.
log
(
typeof
person
.
age
);
// "string"
6
7
var
getAge
=
eval
(
"("
+
person
.
age
+
")"
);
8
console
.
log
(
getAge
);
// ƒ () {return 30;}
9
console
.
log
(
getAge
());
// 30
Copied!
如果不是特殊需求,實際專案不建議這樣的作法,會造成程式維護困難。
用途 4 : 閉包 (Closures) 的應用
透過立即函數的封裝實現閉包應用,例如:
1
var
add
=
(
function
()
{
2
var
counter
=
0
;
3
return
function
()
{
return
counter
+=
1
;}
4
})();
5
6
console
.
log
(
add
);
7
console
.
log
(
add
());
8
console
.
log
(
add
());
9
console
.
log
(
add
());
10
console
.
log
(
counter
);
Copied!
執行結果:
1
ƒ () {return counter += 1;}
2
1
3
2
4
3
5
Uncaught ReferenceError: counter is not defined
Copied!
變數
counter
被宣告於
add()
的函數作用域裡 (Function Scope Level),理論上離開函數就會被消滅。但透過閉包,可以讓
counter
繼續存活,但又不至於被 Global Context 直接操作,只能透過
add()
操控。
關於閉包,我們會另外詳細討論,此處就不贅述。
用途 5 : 瀏覽器書籤小工具
可以把 JavaScript 程式碼包裝成立即函數,存成瀏覽器的書籤,點下去就會立即執行。
例如常見的「解除右鍵」工具就是這種用法:
1
javascript
:
(
function
()
{
function
R
(
a
){
ona
=
"on"
+
a
;
if
(
window
.
addEventListener
)
window
.
addEventListener
(
a
,
function
(
e
)
{
for
(
var
n
=
e
.
originalTarget
;
n
;
n
=
n
.
parentNode
)
n
[
ona
]
=
null
;
},
true
);
window
[
ona
]
=
null
;
document
[
ona
]
=
null
;
if
(
document
.
body
)
document
.
body
[
ona
]
=
null
;
}
R
(
"contextmenu"
);
R
(
"click"
);
R
(
"mousedown"
);
R
(
"mouseup"
);
R
(
"selectstart"
);})()
Copied!
總結
立即函數可以應用的用途:
封裝一次性的 Local Scope
物件實字 (Object Literals) 的屬性初始值產生動態值
將字串內容轉成函數物件
閉包 (Closures) 應用
瀏覽器書籤小工具
相信還有其他應用情境,歡迎補充!
References
W3Schools - JavaScript Functions
Javascript 開發學習心得 - 函數的多種寫法與應用限制
Previous
Day 24:函數呼叫 (Function Invocation) 與立即函數 (Self-Invoking Functions)
Next
Day 26:程式界的哈姆雷特 —— Pass by value, or Pass by reference?
Last modified
1yr ago
Copy link
Contents
立即函數是脫褲子放屁?
用途 1:封裝一次性的 Local Scope
用途 2:為物件實字 (Object Literals) 的屬性初始值產生動態值
用途 3:將字串內容轉成函數物件
用途 4 : 閉包 (Closures) 的應用
用途 5 : 瀏覽器書籤小工具
總結
References