命名功能

函式可以是命名的或未命名的( 匿名函式 ):

var namedSum = function sum (a, b) { // named
    return a + b;
}

var anonSum = function (a, b) { // anonymous
    return a + b;
}

namedSum(1, 3);
anonSum(1, 3);

4
4

但是他們的名字屬於他們自己的範圍:

var sumTwoNumbers = function sum (a, b) {
    return a + b;
}

sum(1, 3);

未捕獲的 ReferenceError:未定義 sum

命名函式與多個場景中的匿名函式不同:

  • 在除錯時,函式的名稱將出現在錯誤/堆疊跟蹤中
  • 命名函式被掛起而匿名函式則不被掛起
  • 處理遞迴時,命名函式和匿名函式的行為會有所不同
  • 根據 ECMAScript 版本,命名和匿名函式可能會以不同方式處理函式 name 屬性

命名函式被懸掛

使用匿名函式時,只能在宣告行之後呼叫該函式,而在宣告之前可以呼叫命名函式。考慮

foo();
var foo = function () { // using an anonymous function
    console.log('bar');
}

未捕獲的 TypeError:foo 不是函式

foo();
function foo () { // using a named function
    console.log('bar');
}

bar

遞迴方案中的命名函式

遞迴函式可以定義為:

var say = function (times) {
    if (times > 0) {
        console.log('Hello!');

        say(times - 1);
    }
}

//you could call 'say' directly, 
//but this way just illustrates the example
var sayHelloTimes = say;

sayHelloTimes(2);

你好!
你好!

如果你的程式碼中某處原始函式繫結被重新定義怎麼辦?

var say = function (times) {
    if (times > 0) {
        console.log('Hello!');

        say(times - 1);
    }
}

var sayHelloTimes = say;
say = "oops";

sayHelloTimes(2);

你好!
未捕獲的 TypeError:說不是函式

這可以使用命名函式來解決

// The outer variable can even have the same name as the function
// as they are contained in different scopes
var say = function say (times) {
    if (times > 0) {
        console.log('Hello!');

        // this time, 'say' doesn't use the outer variable
        // it uses the named function
        say(times - 1);
    }
}

var sayHelloTimes = say;
say = "oops";

sayHelloTimes(2);

你好!
你好!

作為獎勵,命名函式不能設定為 undefined,即使是從內部:

var say = function say (times) {
    // this does nothing
    say = undefined;
    
    if (times > 0) {
        console.log('Hello!');

        // this time, 'say' doesn't use the outer variable
        // it's using the named function
        say(times - 1);
    }
}

var sayHelloTimes = say;
say = "oops";

sayHelloTimes(2);

你好!
你好!

函式的 name 屬性

在 ES6 之前,命名函式將 name 屬性設定為其函式名稱,匿名函式將其 name 屬性設定為空字串。

Version <= 五

var foo = function () {}
console.log(foo.name); // outputs ''

function foo () {}
console.log(foo.name); // outputs 'foo'

在 ES6 之後,命名和未命名的函式都設定了他們的 name 屬性:

Version >= 6

var foo = function () {}
console.log(foo.name); // outputs 'foo'

function foo () {}
console.log(foo.name); // outputs 'foo'

var foo = function bar () {}
console.log(foo.name); // outputs 'bar'