函数声明式和函数表达式的区别

javascript中声明函数常用的方法有两种:函数声明式和函数表达式.

一、定义

下面分别用两种方法定义函数:

//函数声明式
function greeting(){
      console.log("hello world");  
}

//函数表达式
var greeting = function(){
    console.log("hello world"); 
}

二、区别:

    1).以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的。

如果函数表达式声明的函数有函数名,那么这个函数名就相当于这个函数的一个局部变量,只能在函数内部调用,举个栗子:

var f = function fact(x) { 
    if (x <= 1) 
         return 1;
     else 
         return x*fact(x-1);
     };
 alert(fact());   // Uncaught ReferenceError: fact is not defined

    

    2).以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用(函数声明整体会被提升到当前作用域的顶部,函数表达式也提升到顶部但是只有其变量名提升,变量提升详解:https://www.cnblogs.com/vickylinj/p/12190847.html)  :

函数表达式与其他表达式一样,在使用前必须先赋值。以下代码会导致错误。

sayHi(); //错误:函数还不存在
var sayHi = function(){
alert("Hi!");
};

 

    3).以函数声明的方法定义的函数并不是真正的声明,它们仅仅可以出现在全局中,或者嵌套在其他的函数中,但是它们不能出现在循环,条件或者try/catch/finally中,而函数表达式可以在任何地方声明。换句话说,函数声明不是一个完整的语句,所以不能出现在if-else,for循环,finally,try catch语句以及with语句中。

为什么if else 语句里不能用函数声明定义函数,而可以用函数表达式定义函数:

//不要这样做!
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}

表面上看,以上代码表示在 condition 为 true 时,使用一个 sayHi()的定义;否则,就使用另一个定义。实际上,这在 ECMAScript 中属于无效语法, JavaScript 引擎会尝试修正错误,将其转换为合理的状态。但问题是浏览器尝试修正错误的做法并不一致。大多数浏览器会返回第二个声明,忽略condition; Firefox 会在 condition 为 true 时返回第一个声明。因此这种使用方式很危险,不应该
出现在你的代码中。不过,如果是使用函数表达式,那就没有什么问题了。

为什么属于无效的语法呢?这要从词法作用来说,在《JavaScript语言精髓与编程实践》第3章3.2基本语法的结构化含义 ,其中3.2.2.2语法作用域的相关性这一小节回答了以上的疑问,以下属于摘抄部分:

 

上面的代码function的语法作用比表达式的语法作用域高,所以上面if。。。else。。。语句不能包含函数的词法作用域,JavaScript会将其理解为“平行”的关系,即如下所示:

本例中的代码也会理解为:

if(condition){}

else {}


function sayHi(){
alert("Hi!");
}

function sayHi(){
alert("Yo!");

)

相当于第二个sayHi()函数覆盖了第一个,所以会大多数浏览器会返回第二个声明,忽略condition。

当然书中也建议如下作:

//可以这样做
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
};
} else {
sayHi = function(){
alert("Yo!");
};
}

这个例子不会有什么意外,不同的函数会根据 condition 被赋值给 sayHi

参照1:https://www.cnblogs.com/menghome/p/9277855.html

参照2:https://blog.csdn.net/qq_41846861/article/details/92692268

posted @ 2020-01-14 17:01  vickylinj  阅读(2007)  评论(0编辑  收藏  举报