在JavaScript中函数表达式和声明的区别是什么?(复制)

时间:2022-08-26 23:18:48

This question already has an answer here:

这个问题已经有了答案:

What is the difference between the following lines of code?

下面几行代码有什么不同?

//Function declaration
function foo() { return 5; }

//Anonymous function expression
var foo = function() { return 5; }

//Named function expression
var foo = function foo() { return 5; }
  • What is a named/anonymous function expression?
  • 什么是命名/匿名函数表达式?
  • What is a declared function?
  • 什么是已声明的函数?
  • How do browsers deal with these constructs differently?
  • 浏览器如何以不同的方式处理这些构造?

What do the responses to a similar question (var functionName = function() {} vs function functionName() {}) not get exactly right?

对类似问题的响应(var functionName = function() {} vs函数functionName(){})不完全正确?

5 个解决方案

#1


353  

They're actually really similar. How you call them is exactly the same.The difference lies in how the browser loads them into the execution context.

他们实际上非常相似。你怎么称呼他们是完全一样的。不同之处在于浏览器如何将它们加载到执行上下文中。

Function declarations load before any code is executed.

在执行任何代码之前加载函数声明。

Function expressions load only when the interpreter reaches that line of code.

函数表达式只在解释器到达代码行时才加载。

So if you try to call a function expression before it's loaded, you'll get an error! If you call a function declaration instead, it'll always work, because no code can be called until all declarations are loaded.

因此,如果您试图在加载函数表达式之前调用它,您将会得到一个错误!如果您调用一个函数声明,它将一直工作,因为在加载所有声明之前,没有任何代码可以调用。

Example: Function Expression

例子:函数表达式

alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; } 

Example: Function Declaration

例如:函数声明

alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; } 


As for the second part of your question:

关于你问题的第二部分:

var foo = function foo() { return 5; } is really the same as the other two. It's just that this line of code used to cause an error in safari, though it no longer does.

var foo = function foo(){返回5;}和另外两个是一样的。只是这一行代码在safari中会导致错误,尽管它不再这样做了。

#2


85  

Function Declaration

function foo() { ... }

Because of function hoisting, the function declared this way can be called both after and before the definition.

由于函数的提升,这样声明的函数可以在定义前后调用。

Function Expression

  1. Named Function Expression

    命名函数表达式

    var foo = function bar() { ... }
    
  2. Anonymous Function Expression

    匿名函数表达式

    var foo = function() { ... }
    

foo() can be called only after creation.

foo()只能在创建之后调用。

Immediately-Invoked Function Expression (IIFE)

(function() { ... }());

Conclusion

Crockford recommends to use function expression because it makes it clear that foo is a variable containing a function value. Well, personally, I prefer to use Declaration unless there is a reason for Expression.

Crockford建议使用函数表达式,因为它清楚地表明foo是一个包含函数值的变量。嗯,就我个人而言,我更喜欢使用声明,除非有表达的理由。

#3


19  

Regarding 3rd definition:

关于第三个定义:

var foo = function foo() { return 5; }

Heres an example which shows how to use possibility of recursive call:

这里有一个例子,说明了如何使用递归调用的可能性:

a = function b(i) { 
  if (i>10) {
    return i;
  }
  else {
    return b(++i);
  }
}

console.log(a(5));  // outputs 11
console.log(a(10)); // outputs 11
console.log(a(11)); // outputs 11
console.log(a(15)); // outputs 15

Edit: more interesting example with closures:

编辑:闭包更有趣的例子:

a = function(c) {
 return function b(i){
  if (i>c) {
   return i;
  }
  return b(++i);
 }
}
d = a(5);
console.log(d(3)); // outputs 6
console.log(d(8)); // outputs 8

#4


10  

The first statement depends on the context in which it is declared.

第一个语句取决于声明它的上下文。

If it is declared in the global context it will create an implied global variable called "foo" which will be a variable which points to the function. Thus the function call "foo()" can be made anywhere in your javascript program.

如果它在全局上下文中声明,它将创建一个名为“foo”的隐含全局变量,该变量将是指向该函数的变量。因此,可以在javascript程序的任何地方创建名为“foo()”的函数。

If the function is created in a closure it will create an implied local variable called "foo" which you can then use to invoke the function inside the closure with "foo()"

如果函数是在闭包中创建的那么它会创建一个隐含的局部变量"foo"你可以用"foo()"来调用闭包中的函数

EDIT:

编辑:

I should have also said that function statements (The first one) are parsed before function expressions (The other 2). This means that if you declare the function at the bottom of your script you will still be able to use it at the top. Function expressions only get evaluated as they are hit by the executing code.

我还应该说函数语句(第一个)在函数表达式(另外两个)之前被解析,这意味着如果在脚本的底部声明函数,您仍然可以在顶部使用它。函数表达式只有在被执行的代码击中时才被计算。

END EDIT

最后编辑

Statements 2 & 3 are pretty much equivalent to each other. Again if used in the global context they will create global variables and if used within a closure will create local variables. However it is worth noting that statement 3 will ignore the function name, so esentially you could call the function anything. Therefore

表述2和3几乎是等价的。同样,如果在全局上下文中使用,它们将创建全局变量,如果在闭包中使用,则将创建局部变量。但是值得注意的是,语句3将忽略函数名,因此在实际中您可以调用函数任何值。因此

var foo = function foo() { return 5; }

Is the same as

是一样的

var foo = function fooYou() { return 5; }

#5


1  

Though the complete difference is more complicated, the only difference that concerns me is when the machine creates the function object. Which in the case of declarations is before any statement is executed but after a statement body is invoked (be that the global code body or a sub-function's), and in the case of expressions is when the statement it is in gets executed. Other than that for all intents and purposes browsers treat them the same.

虽然完全的差别比较复杂,但是我关心的唯一不同是机器创建函数对象时的区别。在声明的情况下,在执行任何语句之前,但是在调用语句主体(无论是全局代码主体还是子函数)之后,在表达式的情况下,是在执行语句时。除此之外,浏览器对它们都一视同仁。

To help you understand, take a look at this performance test which busted an assumption I had made of internally declared functions not needing to be re-created by the machine when the outer function is invoked. Kind of a shame too as I liked writing code that way.

为了帮助您理解,请查看这个性能测试,它打破了我所做的假设,即在调用外部函数时,内部声明的函数不需要由机器重新创建。有点遗憾,因为我喜欢这样写代码。

#1


353  

They're actually really similar. How you call them is exactly the same.The difference lies in how the browser loads them into the execution context.

他们实际上非常相似。你怎么称呼他们是完全一样的。不同之处在于浏览器如何将它们加载到执行上下文中。

Function declarations load before any code is executed.

在执行任何代码之前加载函数声明。

Function expressions load only when the interpreter reaches that line of code.

函数表达式只在解释器到达代码行时才加载。

So if you try to call a function expression before it's loaded, you'll get an error! If you call a function declaration instead, it'll always work, because no code can be called until all declarations are loaded.

因此,如果您试图在加载函数表达式之前调用它,您将会得到一个错误!如果您调用一个函数声明,它将一直工作,因为在加载所有声明之前,没有任何代码可以调用。

Example: Function Expression

例子:函数表达式

alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; } 

Example: Function Declaration

例如:函数声明

alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; } 


As for the second part of your question:

关于你问题的第二部分:

var foo = function foo() { return 5; } is really the same as the other two. It's just that this line of code used to cause an error in safari, though it no longer does.

var foo = function foo(){返回5;}和另外两个是一样的。只是这一行代码在safari中会导致错误,尽管它不再这样做了。

#2


85  

Function Declaration

function foo() { ... }

Because of function hoisting, the function declared this way can be called both after and before the definition.

由于函数的提升,这样声明的函数可以在定义前后调用。

Function Expression

  1. Named Function Expression

    命名函数表达式

    var foo = function bar() { ... }
    
  2. Anonymous Function Expression

    匿名函数表达式

    var foo = function() { ... }
    

foo() can be called only after creation.

foo()只能在创建之后调用。

Immediately-Invoked Function Expression (IIFE)

(function() { ... }());

Conclusion

Crockford recommends to use function expression because it makes it clear that foo is a variable containing a function value. Well, personally, I prefer to use Declaration unless there is a reason for Expression.

Crockford建议使用函数表达式,因为它清楚地表明foo是一个包含函数值的变量。嗯,就我个人而言,我更喜欢使用声明,除非有表达的理由。

#3


19  

Regarding 3rd definition:

关于第三个定义:

var foo = function foo() { return 5; }

Heres an example which shows how to use possibility of recursive call:

这里有一个例子,说明了如何使用递归调用的可能性:

a = function b(i) { 
  if (i>10) {
    return i;
  }
  else {
    return b(++i);
  }
}

console.log(a(5));  // outputs 11
console.log(a(10)); // outputs 11
console.log(a(11)); // outputs 11
console.log(a(15)); // outputs 15

Edit: more interesting example with closures:

编辑:闭包更有趣的例子:

a = function(c) {
 return function b(i){
  if (i>c) {
   return i;
  }
  return b(++i);
 }
}
d = a(5);
console.log(d(3)); // outputs 6
console.log(d(8)); // outputs 8

#4


10  

The first statement depends on the context in which it is declared.

第一个语句取决于声明它的上下文。

If it is declared in the global context it will create an implied global variable called "foo" which will be a variable which points to the function. Thus the function call "foo()" can be made anywhere in your javascript program.

如果它在全局上下文中声明,它将创建一个名为“foo”的隐含全局变量,该变量将是指向该函数的变量。因此,可以在javascript程序的任何地方创建名为“foo()”的函数。

If the function is created in a closure it will create an implied local variable called "foo" which you can then use to invoke the function inside the closure with "foo()"

如果函数是在闭包中创建的那么它会创建一个隐含的局部变量"foo"你可以用"foo()"来调用闭包中的函数

EDIT:

编辑:

I should have also said that function statements (The first one) are parsed before function expressions (The other 2). This means that if you declare the function at the bottom of your script you will still be able to use it at the top. Function expressions only get evaluated as they are hit by the executing code.

我还应该说函数语句(第一个)在函数表达式(另外两个)之前被解析,这意味着如果在脚本的底部声明函数,您仍然可以在顶部使用它。函数表达式只有在被执行的代码击中时才被计算。

END EDIT

最后编辑

Statements 2 & 3 are pretty much equivalent to each other. Again if used in the global context they will create global variables and if used within a closure will create local variables. However it is worth noting that statement 3 will ignore the function name, so esentially you could call the function anything. Therefore

表述2和3几乎是等价的。同样,如果在全局上下文中使用,它们将创建全局变量,如果在闭包中使用,则将创建局部变量。但是值得注意的是,语句3将忽略函数名,因此在实际中您可以调用函数任何值。因此

var foo = function foo() { return 5; }

Is the same as

是一样的

var foo = function fooYou() { return 5; }

#5


1  

Though the complete difference is more complicated, the only difference that concerns me is when the machine creates the function object. Which in the case of declarations is before any statement is executed but after a statement body is invoked (be that the global code body or a sub-function's), and in the case of expressions is when the statement it is in gets executed. Other than that for all intents and purposes browsers treat them the same.

虽然完全的差别比较复杂,但是我关心的唯一不同是机器创建函数对象时的区别。在声明的情况下,在执行任何语句之前,但是在调用语句主体(无论是全局代码主体还是子函数)之后,在表达式的情况下,是在执行语句时。除此之外,浏览器对它们都一视同仁。

To help you understand, take a look at this performance test which busted an assumption I had made of internally declared functions not needing to be re-created by the machine when the outer function is invoked. Kind of a shame too as I liked writing code that way.

为了帮助您理解,请查看这个性能测试,它打破了我所做的假设,即在调用外部函数时,内部声明的函数不需要由机器重新创建。有点遗憾,因为我喜欢这样写代码。