1、背景介绍
定义函数的方法主要有三种:
1:函数声明(Function Declaration)
2:函数表达式Function Expression)
3:new Function构造函数
其中,经常使用的是函数声明和函数表达式的函数定义方法,这两种方法有着很微妙的区别和联系,
而且这两种方法的使用也容易混淆,所以我们来讲一下两者有哪些不同之处
2:知识剖析
函数声明的典型格式:
function functionName(arg1, arg2, ...){}
函数表达式
函数表达式的典型格式:
var variable=function(arg1, arg2, ...){}
3、常见问题
两者具体有哪些区别呢
4:解决方案
一、Javascript引擎在解析javascript代码时会‘函数声明提升'(Function declaration Hoisting)
当前执行环境(作用域)上的函数声明,而函数表达式必须等到Javascirtp引擎执行到它所在行时,
才会从上而下一行一行地解析函数表达式
,二、函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fn()形式调用 。
以下是两者差别的两个例子。
fn1();//不会报错,因为"提升了"函数声明,函数调用可在函数声明之前
functionfn1(){
console.log("这里是函数声明");
}
fn2();//会报错,变量fn2还未保存对函数的引用,函数调用必须在函数表达式之后
varfn2=function(){
console.log("这里是函数表达式");
}
关于立即执行函数的讨论
//情况1
//结果会被输出
varfn=function(){
console.log("函数表达式赋值给一个变量");
}();
//情况2
//结果不会被输出,JavaScript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
functionfn(){
console.log("函数声明");
}();
//情况3
//语法错误,匿名函数属于函数表达式,未执行赋值操作,不能被调用
function(){
console.log("函数表达式");
}();
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)