发表于: 2017-07-25 20:20:47

1 856


函数声明和函数表达式有什么区别

1、背景介绍

定义函数的方法主要有三种:

1:函数声明(Function Declaration)

2:函数表达式Function Expression)

3:new Function构造函数

其中,经常使用的是函数声明和函数表达式的函数定义方法,这两种方法有着很微妙的区别和联系,

而且这两种方法的使用也容易混淆,所以我们来讲一下两者有哪些不同之处


2:知识剖析

函数声明的典型格式:

function functionName(arg1, arg2, ...){    <!-- function body -->}
函数表达式
  • 函数表达式的典型格式:

    var  variable=function(arg1, arg2, ...){            <!-- function body -->}


3、常见问题


两者具体有哪些区别呢


4:解决方案


一、Javascript引擎在解析javascript代码时会‘函数声明提升'(Function declaration Hoisting)

当前执行环境(作用域)上的函数声明,而函数表达式必须等到Javascirtp引擎执行到它所在行时,

才会从上而下一行一行地解析函数表达式


,二、函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fn()形式调用 。

以下是两者差别的两个例子。

  1. <script type="text/javascript">  
  2.             fn1();//不会报错,因为"提升了"函数声明,函数调用可在函数声明之前  
  3.             function fn1(){  
  4.                 console.log("这里是函数声明");  
  5.             }  
  6.               
  7.             fn2();//会报错,变量fn2还未保存对函数的引用,函数调用必须在函数表达式之后  
  8.             var fn2=function(){  
  9.                 console.log("这里是函数表达式");  
  10.             }  
  11.         </script> 


关于立即执行函数的讨论

  1. <script type="text/javascript">  
  2.             //情况1  
  3.             //结果会被输出  
  4.             var fn=function(){  
  5.                 console.log("函数表达式赋值给一个变量");  
  6.             }();  
  7.             //情况2  
  8.             //结果不会被输出,JavaScript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用  
  9.             function fn(){  
  10.                 console.log("函数声明");  
  11.             }();  
  12.             //情况3  
  13.             //语法错误,匿名函数属于函数表达式,未执行赋值操作,不能被调用  
  14.             function(){  
  15.                 console.log("函数表达式");  
  16.             }();  
  17.               
  18.         </script>   


5:编码实战


同上


6:深度思考


使用两种方式创建函数时都发生了什么



函数声明解析过程如下:

1. 创建一个new Function对象,FormalParameterList指定参数,FunctionBody指定函数体。

将当前正在运行环境中作用域链作为它的作用域。

2. 为当前变量对象创建一个名为Identifier的属性,值为Result(1)。


具名函数表达式的解析过程如下:


1. 创建一个new Object对象
2. 将Result(1)添加到作用域链的顶端
3. 创建一个new Function对象,FormalParameterList指定参数,FunctionBody指定函数体。将当前正在运行的执行环境中作用域链作为它的作用域。
4. 为Result(1)创建一个名为Identifier 的属性,其值为为Result(3),只读,不可删除
5. 从作用域链中移除Result(1)
6. 返回Result(3)








返回列表 返回列表
评论

    分享到