函數(shù)聲明
在JavaScript中,對(duì)于函數(shù)的聲明有兩種表達(dá)形式, 聲明式 和 表達(dá)式 ,至于其他函數(shù)(如立即執(zhí)行函數(shù),箭頭函數(shù)等)都是基于這兩種形式衍生的。
// 聲明式
function foo () {
console.log('我是聲明式')
}
// 表達(dá)式
var foo = function () {
console.log('我是表達(dá)式')
}
具名函數(shù)
故名思意,具名函數(shù)就是有名稱的函數(shù),這是我們最常見的一種函數(shù),我們先來(lái)看看它的寫法。
// 具名函數(shù)
function foo () {
console.log('我是具名函數(shù)')
}
上邊說(shuō)了,函數(shù)聲明的表達(dá)形式有兩種,具名函數(shù)是經(jīng)典的聲明式,具名函數(shù)表達(dá)式的另外一種表現(xiàn)形式引出了另外一種函數(shù)類型- 具名函數(shù)表達(dá)式(NFE) 。
具名函數(shù)表達(dá)式
具名函數(shù)表達(dá)式就是具名函數(shù)的表達(dá)式寫法,嚴(yán)格來(lái)說(shuō),它并不是一種函數(shù)類型,只是一種寫法而已。
// 具名函數(shù)表達(dá)式
var fn = function foo () {
console.log('我是具名函數(shù)表達(dá)式');
}
fn() // 輸出:我是具名函數(shù)表達(dá)式
它有幾個(gè)特點(diǎn):
- 函數(shù)名標(biāo)識(shí)符私有化
- 函數(shù)名標(biāo)識(shí)符常量化
函數(shù)名標(biāo)識(shí)符私有化:即具名函數(shù)表達(dá)式的函數(shù)名不能從外部調(diào)用,僅供函數(shù)體內(nèi)部使用,當(dāng)外部調(diào)用時(shí)就會(huì)報(bào)錯(cuò)。
// 函數(shù)名稱私有化
var fn = function foo () {
console.log(typeof foo);
}
fn() // function
foo() // Uncaught ReferenceError: foo is not defined
函數(shù)名標(biāo)識(shí)符常量化:即具名函數(shù)表達(dá)式標(biāo)識(shí)符的值不能修改,我們可以將其當(dāng)作常量來(lái)使用。
var fn = function foo(){
foo = 12;
console.log(foo);
}
fn()
/*
輸出:
ƒ foo(){
foo = 12;
console.log(foo);
}
*/
我們來(lái)看一道經(jīng)典的面試題
// 改寫以下代碼,使其分別輸出10、12
var foo = 10;
(function foo (){
foo = 12;
console.log(foo);
})()
// 改寫結(jié)果
var foo = 10;
(function foo (){
var foo = 12;
console.log(window.foo); // 10
console.log(foo); // 12
})()
匿名函數(shù):即沒有名稱的函數(shù),匿名函數(shù)不能像具名函數(shù)一樣直接聲明定義,在JavaScript中常見的用法就是將匿名函數(shù)當(dāng)作回調(diào)參數(shù)使用或作為高階函數(shù)的返回值。
// 作為回調(diào)參數(shù)
setTimeout(function () {
console.log('我是匿名函數(shù)');
}, 1000);
// 作為高階函數(shù)的返回值
function foo () {
var num = 10;
return function (i) {
return num + i;
}
}
foo()(5) // 輸出:15
匿名函數(shù)有幾個(gè)缺點(diǎn)我們需要注意一下:
- 沒有函數(shù)名,調(diào)試?yán)щy
- 如需引用自身(如遞歸函數(shù)),需要用 arguments.callee ,但是 arguments.callee 在嚴(yán)格模式下禁用
- 可讀性差
立即執(zhí)行函數(shù)
立即執(zhí)行函數(shù)(IIFE):即當(dāng)程序解析到該函數(shù)時(shí)就立即執(zhí)行。
// 寫法一
(function () {
console.log('我是立即執(zhí)行函數(shù)');
})()
// 寫法二
(function () {
console.log('我是立即執(zhí)行函數(shù)');
}())
匿名函數(shù)的優(yōu)點(diǎn)在于內(nèi)部參數(shù)不會(huì)泄露,即變量私有化。
(function () {
var x = 10
console.log('我是立即執(zhí)行函數(shù)');
}())
console.log(x); // Uncaught ReferenceError: x is not defined
有一道很經(jīng)典的面試題,我們可以看一下。
// 改寫以下代碼,讓其依次輸出.
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(`值為${i}`)
}, 0)
}
// 此時(shí)會(huì)輸出5次 "值為5"
我們會(huì)立馬想到用 let ,但是還有沒有其他寫法呢?當(dāng)然有,立即執(zhí)行函數(shù)就是了。
// 改寫方法一
for (var i = 0; i < 5; i++) {
(function(num){
console.log(`值為${num}`)
})(i)
}
// 改寫方法二
for (var i = 0; i < 5; i++) {
var num = (function(){
return i;
})()
console.log(`值為${num}`)
}
原文地址:https://juejin.im/post/6891565170167021576?utm_source=tuicool&utm_medium=referral