当变量等于函数时,它意味着什么?

时间:2012-02-27 14:59:25

标签: javascript function coding-style convention

  

可能重复:
  JavaScript: var functionName = function() {} vs function functionName() {}

在JavaScript中,将变量定义为函数的目的是什么?我以前见过这个惯例,并没有完全理解它。

例如,在脚本中的某个时刻,会调用一个函数:

whatever();

但是我期望看到一个名为whatever的函数,就像这样:

function whatever(){

}

相反,我会看到一个名为whatever的变量,它被定义为一个函数,如下所示:

var whatever = function(){

}

这是为了什么目的?你为什么要这样做而不只是命名函数?

5 个答案:

答案 0 :(得分:34)

注意:请参阅答案末尾的更新,块内的声明变得有效(但如果您没有使用严格模式,则相当复杂)。


这是一个原因:

var whatever;

if (some_condition) {
    whatever = function() {
        // Do something
    };
}
else {
    whatever = function() {
        // Do something else
    };
}
whatever();

您可能会在库的初始化中看到类似的代码,这些代码必须处理实现差异(例如Web浏览器之间的差异,IE浏览器attachEvent与标准addEventListener之间的差异)。您不能使用函数声明来执行等效操作:

if (some_condition) {
    function whatever() {    // <=== DON'T DO THIS
        // Do something
    }
}
else {
    function whatever() {    // <=== IT'S INVALID
        // Do something else
    }
}
whatever();

...它们未在控制结构中指定,因此允许JavaScript引擎执行他们想要的操作,并且不同的引擎已完成不同的操作。 (编辑:再次,请参阅下面的说明,现在已经指定了。)

另外,

之间存在很大差异
var whatever = function() {
    // ...
};

function whatever() {
    // ...
}

第一个是函数表达式,当代码在逐步执行上下文时达到该点(例如,它所处的函数,或者逐步执行)时,它会被评估 - 执行全局代码)。它还会产生一个匿名函数(引用它的变量有一个名称,但函数没有,这对helping your tools to help you有影响。)

第二个是函数声明,在进入上下文时进行评估, 执行任何分步代码。 (有些人称之为“悬挂”,因为源中的某些东西比源中更高的东西更早发生。)该函数也有一个正确的名称。

所以考虑一下:

function foo() {
    doSomething();
    doSomethingElse();
    console.log("typeof bar = " + typeof bar); // Logs "function"

    function bar() {
    }
}

,而

function foo() {
    doSomething();
    doSomethingElse();
    console.log("typeof bar = " + typeof bar); // Logs "undefined"

    var bar = function() {
    };
}

在第一个示例中,使用声明,在 doSomething之前处理声明并运行其他逐步代码。在第二个示例中,因为它是表达式,所以它作为逐步代码的一部分执行,因此上面没有定义函数(变量在上面定义,因为var is also "hoisted"

结束:目前,你不能在一般的客户端网站上做到这一点:

var bar = function foo() { // <=== Don't do this in client-side code for now
    // ...
};

应该能够做到这一点,它被称为命名函数表达式,它是一个函数表达式,为函数提供了一个正确的名称。但是各种各样的JavaScript引擎都错了,IE continued to get very wrong indeed until very recently


ES2015更新+

从ES2015(又名“ES6”)开始,块中的函数声明被添加到规范中。

严格模式

在严格模式下,新指定的行为简单易懂:它们的范围限定在它们出现的块中,并被提升到它的顶部。

所以这个:

"use strict";
if (Math.random() < 0.5) {
  foo();
  function foo() {
    console.log("low");
  }
} else {
  foo();
  function foo() {
    console.log("high");
  }
}
console.log(typeof foo); // undefined

(注意对函数的调用是上面块中的函数。)

...基本上等同于:

"use strict";
if (Math.random() < 0.5) {
  let foo = function() {
    console.log("low");
  };
  foo();
} else {
  let foo = function() {
    console.log("high");
  };
  foo();
}
console.log(typeof foo); // undefined

松散模式

松散模式行为要复杂得多,而且理论上它在Web浏览器中的JavaScript引擎和Web浏览器中的 之间的JavaScript引擎之间有所不同。我不会在这里介绍它。只是不要这样做。如果你坚持使用块中的函数声明,那么使用严格模式,它们是有意义的,并且在不同的环境中是一致的。

答案 1 :(得分:2)

这样你就可以将函数存储在变量中,例如将它们作为参数传递给其他函数。这有用的一个例子是编写异步函数,它们将回调作为参数传递给

var callback = function() { console.log('done', result)}

var dosomething = function(callback) {
    //do some stuff here
    ...
    result = 1;
    callback(result);
}

由于函数是javascript中的对象,因此您也可以使用属性和方法扩展它们。

答案 2 :(得分:1)

将函数赋值给变量时,可以将其作为参数传递给其他函数,并将其扩展为使用Javascript的对象模型。

答案 3 :(得分:0)

JavaScript中的函数是对象;换句话说,他们是。因此,无论函数如何定义,您都可以始终设置变量以引用函数:

function foo() { ... }

var anotherFoo = foo;
anotherFoo(); // calls foo

函数是可以用作对象属性,函数参数,数组元素以及一般值可以在JavaScript中执行的任何其他操作的值。它们是对象,也可以拥有自己的属性。

答案 4 :(得分:0)

如果在函数内使用“var”声明函数变量,则只能在该函数中访问变量 。退出该函数时,该变量将被销毁。这些变量称为局部变量。您可以在不同的函数中使用相同名称的局部变量,因为每个函数只能被声明它的函数识别。