JavaScript 中,定义函数时用 var foo = function () {} 和 function foo() 有什么区别?

方法一: var foo = function () { //code } 方法二: function foo () { //code } 看别人的代码好像大家偏好第一种方式多一点。 我所知的区别在于第一种方式在需要在调用前出现,第二种方式位置不重要,可以放到最后。 请问他们还有别的区别吗?
关注者
205
被浏览
35006

19 个回答

这个问题其实非常好,最关键的区别在于JavaScript 函数和变量声明的“提前”(hoist)行为。
the Google style guide 建议我们采用方法一。

简单的说 如果我们使用 匿名函数
var FUNCTION_NAME = function() { /* FUNCTION_BODY */}; 

这种方式, 编译后变量声明FUNCTION_NAME 会“被提前”了,但是他的赋值(也就是FUNCTION_BODY)并不会被提前。
也就是,匿名函数只有在被调用时才被初始化。

如果我们使用
function FUNCTION_NAME () 
{ /* FUNCTION_BODY */}; 

这种方式, 编译后函数声明和他的赋值都会被提前。
也就是说函数声明过程在整个程序执行之前的预处理就完成了,所以只要处于同一个作用域,就可以访问到,即使在定义之前调用它也可以。


请先看一个例子
function hereOrThere() { //function statement
  return 'here';
}

alert(hereOrThere()); // alerts 'there'

function hereOrThere() {
  return 'there';
}

我们会发现alert(hereOrThere) 语句执行时会alert('there')!这里的行为其实非常出乎意料,主要原因是JavaScript 函数声明的“提前”行为,简而言之,就是Javascript允许我们在变量和函数被声明之前使用它们,而第二个定义覆盖了第一种定义。换句话说,上述代码编译之后相当于


function hereOrThere() { //function statement
  return 'here';
}

function hereOrThere() {//申明前置了,但因为这里的申明和赋值在一起,所以一起前置
  return 'there';
}

alert(hereOrThere()); // alerts 'there'

强烈推荐阅读下面文章,JavaScript 中对变量和函数声明的“提前(hoist)”


再看下面一个例子:


var hereOrThere = function() { // function expression
  return 'here';
};

alert(hereOrThere()); // alerts 'here'

hereOrThere = function() {
  return 'there';
};
这里就是我们期待的behavior,这段程序编译之后相当于:

var hereOrThere;//申明前置了

hereOrThere = function() { // function expression
  return 'here';
};

alert(hereOrThere()); // alerts 'here'

hereOrThere = function() {
  return 'there';
};


参考 Frequently Misunderstood JavaScript Concepts The Syntax for Defining a Function is Significant
  • 方法一:foo在进入函数执行上下文开始执行代码的时候,foo是undefined的,知道执行完var foo = function () { }这句,foo才会得到赋值;
  • 方法二:在进入函数执行上下文开始执行代码的时候,foo已经是一个function了。

想深入了解内幕的,具体可以参考variable object。dmitrysoshnikov.com/ecm