作为变量的功能

正常的函数声明如下所示:

function foo(){
}

这样定义的函数可以通过其名称从其上下文中的任何位置访问。但有时候处理像对象引用这样的函数引用会很有用。例如,你可以根据某些条件将对象分配给变量,然后从一个或另一个对象中检索属性:

var name = 'Cameron';
var spouse;

if ( name === 'Taylor' ) spouse = { name: 'Jordan' };
else if ( name === 'Cameron' ) spouse = { name: 'Casey' };

var spouseName = spouse.name;

在 JavaScript 中,你可以使用函数执行相同的操作:

// Example 1
var hashAlgorithm = 'sha1';
var hash;

if ( hashAlgorithm === 'sha1' ) hash = function(value){ /*...*/ };
else if ( hashAlgorithm === 'md5' ) hash = function(value){ /*...*/ };

hash('Fred');

在上面的例子中,hash 是一个普通变量。它被赋予对函数的引用,之后可以使用括号调用它引用的函数,就像正常的函数声明一样。

上面的示例引用了匿名函数…没有自己名称的函数。你还可以使用变量来引用命名函数。上面的例子可以这样重写:

// Example 2
var hashAlgorithm = 'sha1';
var hash;

if ( hashAlgorithm === 'sha1' ) hash = sha1Hash;
else if ( hashAlgorithm === 'md5' ) hash = md5Hash;

hash('Fred');

function md5Hash(value){
    // ...
}

function sha1Hash(value){
    // ...
}

或者,你可以从对象属性分配函数引用:

// Example 3
var hashAlgorithms = {
    sha1: function(value) { /**/ },
    md5: function(value) { /**/ }
};

var hashAlgorithm = 'sha1';
var hash;

if ( hashAlgorithm === 'sha1' ) hash = hashAlgorithms.sha1;
else if ( hashAlgorithm === 'md5' ) hash = hashAlgorithms.md5;

hash('Fred');

你可以通过省略括号将对一个变量所持有的函数的引用分配给另一个变量。这可能导致一个容易犯的错误:尝试将函数的返回值分配给另一个变量,但意外地将该引用分配给该函数。

// Example 4
var a = getValue;
var b = a; // b is now a reference to getValue.
var c = b(); // b is invoked, so c now holds the value returned by getValue (41)

function getValue(){
    return 41;
}

对函数的引用与任何其他值类似。如你所见,可以将引用分配给变量,然后可以将该变量的引用值分配给其他变量。你可以像传递任何其他值一样传递对函数的引用,包括将对函数的引用作为另一个函数的返回值传递。例如:

// Example 5
// getHashingFunction returns a function, which is assigned
// to hash for later use:
var hash = getHashingFunction( 'sha1' );
// ...
hash('Fred');

// return the function corresponding to the given algorithmName
function getHashingFunction( algorithmName ){
    // return a reference to an anonymous function
    if (algorithmName === 'sha1') return function(value){ /**/ };
    // return a reference to a declared function
    else if (algorithmName === 'md5') return md5;
}

function md5Hash(value){
    // ...
}

你无需为变量分配函数引用即可调用它。这个示例构建示例 5,将调用 getHashingFunction,然后立即调用返回的函数并将其返回值传递给 hashedValue。

// Example 6
var hashedValue = getHashingFunction( 'sha1' )( 'Fred' );

关于吊装的注意事项

请记住,与普通函数声明不同,引用函数的变量不是悬挂的。在示例 2 中,md5Hashsha1Hash 函数在脚本的底部定义,但可以立即在任何地方使用。无论你在何处定义函数,解释器都会将其提升到其范围的顶部,使其立即可用。这是变量定义的情况下,所以如下面的代码将打破:

var functionVariable;

hoistedFunction(); // works, because the function is "hoisted" to the top of its scope
functionVariable(); // error: undefined is not a function.

function hoistedFunction(){}
functionVariable = function(){};