【问题标题】:What does it mean when a variable equals a function? [duplicate]变量等于函数是什么意思? [复制]
【发布时间】:2012-03-17 01:14:58
【问题描述】:

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

在 JavaScript 中,将变量定义为函数的目的是什么?我以前看过这个约定,但并不完全理解。

例如,在某个脚本中,函数的调用方式如下:

whatever();

但我希望看到一个名为 whatever 的函数,如下所示:

function whatever(){

}

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

var whatever = function(){

}

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

【问题讨论】:

标签: javascript function coding-style convention


【解决方案1】:

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


这是一个原因:

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")。

结束:目前,您无法在一般的客户端 Web 内容中执行此操作:

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 引擎not之间有所不同。我不会在这里讨论它。只是不要这样做。如果您坚持在块中声明函数,请使用严格模式,在这种模式下它们有意义并且跨环境保持一致。

【讨论】:

  • 非常有用,谢谢:)
  • @DanielAndresAcevedo:谢谢。它也有点过时了,我在最后添加了一个注释。
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

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

    function foo() { ... }
    
    var anotherFoo = foo;
    anotherFoo(); // calls foo
    

    函数是可以用作对象属性、函数参数、数组元素以及通用值在 JavaScript 中可以做的任何其他事情的值。它们是对象,也可以有自己的属性。

    【讨论】:

      【解决方案4】:

      当您将函数分配给变量时,您可以将其作为参数传递给其他函数,也可以对其进行扩展以使用 Javascript 的对象模型。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-08
          • 2011-05-22
          • 2011-06-11
          • 2021-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-21
          相关资源
          最近更新 更多