愛總結(jié)挽唉,愛搬磚,愛生活
引言
偶然之間看到一個問題定踱,問題是這樣的:
(function() {}());
(function() {})();
上面這兩種寫法有沒有什么區(qū)別棍潘?
打眼一看這個問題不太好回答,這說明了一個問題崖媚,我對這類立即調(diào)用的函數(shù)表達式還不熟悉亦歉,這個時候應(yīng)該去百度看看大家怎么理解立即調(diào)用的函數(shù)表達式。
心得
- 立即調(diào)用的函數(shù)表達式(在這之前我一直稱呼它為立即執(zhí)行函數(shù)畅哑,經(jīng)過此番探索更正了之前不合理的叫法)
- 立即調(diào)用的函數(shù)表達式的作用:
- 不必為函數(shù)命名肴楷,避免污染全局作用域;
- 立即調(diào)用的函數(shù)表達式內(nèi)部形成了一個單獨的作用域荠呐,可以封裝一些外部無法讀取的私有變量和方法赛蔫。
回顧
先從函數(shù)的定義和使用說起
// 函數(shù)聲明
function foo() {
console.log('foo')
}
// 函數(shù)表達式
var bar = function() {
console.log('bar')
}
// 調(diào)用
foo()
bar()
- 上述兩種方式是開發(fā)中常用的函數(shù)定義和調(diào)用方式,回憶一下這兩種定義函數(shù)的方式泥张;
- 函數(shù)聲明是會發(fā)生函數(shù)提升的呵恢,允許在定義之前使用
- 函數(shù)表達是不會發(fā)生函數(shù)提升,是不允許在定義之前使用的圾结,函數(shù)表達是可以是一個匿名函數(shù)(上面這樣的)瑰剃,也可以是一個命名函數(shù)(下面這樣)
// 函數(shù)表達式 var rn = function rn() { console.log('rn') }
- 關(guān)于函數(shù)定義的回顧到此為止,接下來探究立即調(diào)用的函數(shù)表達式
立即調(diào)用的函數(shù)表達式
- 文章開頭給出的兩種寫法
(function() {}());
(function() {})();
- 要知道這兩種寫法有沒有區(qū)別筝野,那就得先弄清楚為什么會這樣寫晌姚,添上一對括號的作用是什么粤剧?不加這對括號可不可以?
括號的作用
函數(shù)定義后立即調(diào)用的解決方法挥唠,就是不要讓function出現(xiàn)在行首抵恋,讓引擎將其理解成一個表達式。最簡單的處理宝磨,就是將其放在一個圓括號里面弧关。
- 總結(jié)一下前面兩段話的意思:要讓函數(shù)定義后能被立即調(diào)用,就是要讓代碼被當(dāng)作表達式解析唤锉,一種解決方法就是加圓括號世囊;
- 既然括號的作用只是讓代碼在解析時被解析成表達式,所以文章開頭提到的兩種寫法是沒有區(qū)別的窿祥,不過
(function() {}())
這種寫法更多的被推薦株憾。
不加括號可不可以?
為了避免解析的歧義晒衩,JavaScript 規(guī)定嗤瞎,如果function關(guān)鍵字出現(xiàn)在行首,一律解釋成語句听系。因此贝奇,引擎看到行首是function關(guān)鍵字之后,認為這一段都是函數(shù)的定義靠胜,不應(yīng)該以圓括號結(jié)尾掉瞳,所以就報錯了。
- 針對文章開頭的兩種寫法不加括號是不可以的髓帽,當(dāng)然還有更多的方法實現(xiàn)函數(shù)定義是就調(diào)用菠赚,這些方式都是被允許的,使用了不同的方式讓一個語句變成表示式郑藏,這也可以理解為什么叫它立即調(diào)用的函數(shù)表達式
var rn = function rn() { console.log('rn') }();
true && function(){ console.log(1) }();
0, function(){ console.log(2) }();
// 這種方式是被推薦的
!function () { console.log(3) }();
~function () { console.log(4) }();
-function () { console.log(5) }();
+function () { console.log(6) }();
注意:(function() {}())
、(function() {})()
使用這兩種寫法時瘩欺,代碼所在的上一行代碼結(jié)束必須有分號必盖,或者寫成這個樣子;(function() {}())
、;(function() {})()
俱饿。
使用場景
- 封裝特定功能的模塊歌粥,起初JQuery就是使用的這種方式;
- 還記得這個案例嗎
<button class="btn">0</button>
<button class="btn">1</button>
<button class="btn">2</button>
<button class="btn">3</button>
<script>
var btns = document.getElementsByClassName('btn')
for(var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
console.log(i);
}
}
</script>
- 上面這個案例中在點擊任意按鈕的時候打印的都是
4
拍埠,原因不必再做解釋(使用let聲明i變量也可以解決這個問題)失驶,現(xiàn)在咱們用立即調(diào)用的函數(shù)表達式讓點擊按鈕打印不同的值;
// 只貼出了兩種解決方式的js代碼
// 第一種解決方式
var btns = document.getElementsByClassName('btn')
for(var i = 0; i < btns.length; i++) {
btns[i].onclick = (function(i) {
return function() {
console.log(i)
}
}(i))
}
// 第二種解決方式
var btns = document.getElementsByClassName('btn')
for(var i = 0; i < btns.length; i++) {
(function(i) {
btns[i].onclick = function() {
console.log(i)
}
}(i))
}
參考文章
愛總結(jié)枣购,愛搬磚嬉探,愛生活