1、函数表达式
如下都是表达式:
- var a = 1;
- var b = {};
- var c = function () {};
- var d = [];
- var e = '';
- var f = true;
- var g = null;
函数表达式,指的是定义的变量指向的是一个函数,如上的变量c。继续看下面这个经典的函数表达式例子。
- var a = 1;
- var b = function () {
- alert(a);
- var a = 3;
- alert(a);
- }
- b();
结果分别弹出了undefined和3。因为在javascript里,在同一个作用域里表达式的定义都会被首先解释器解析,如上可以理解为:
- // 在同一个作用域里变量定义被提前
- var a;
- var b;
-
- // 变量赋值
- a = 1;
- b = function () {
- // 在同一个作用域里变量定义被提前
- var a;
- alert(a);
- a = 3;
- alert(a);
- }
-
- b();
这一点,在各种浏览器中都解释一致。
2、函数声明式
函数声明式,仅对函数而言。如:
- a();
-
- function a() {
- alert(1);
- }
函数声明式,指的是使用function关键字定义一个函数,并且会使函数的定义和赋值同时进行,以上等同于:
- // 在同一个作用域里函数声明式被提前定义
- var a;
-
- // 在同一个作用域里函数声明式被提前赋值
- a = function () {
- alert(1);
- }
-
- a();
而函数表达式就没有这样的结果,如:
- try {
- a();
- } catch(e) {
- alert('a函数调用失败!');
- }
-
- var a = function () {
- alert(1);
- };
如上例子,最后执行结果是弹出了“a函数调用失败!”。上个例子可以这么理解:
- // 在同一个作用域里,变量被提前定义
- var a;
-
- // 此时调用a的时候,a的值为 undefined
- try {
- a();
- } catch (e) {
- alert('a函数调用失败!');
- }
-
- // 变量的赋值位置不变
- a = function () {
- alert(1);
- };
3、函数表达式与函数声明式
由2可知,函数声明式的优先级的是高于函数表达式的,例证:
- var a = function () {
- alert(1);
- };
-
- function a() {
- alert(2);
- }
-
- a();
以上例子弹出a的结果为1,而不是2,可以理解为:
- // 在同一个作用域里由函数声明式定义的变量 a
- var a;
-
- // 在同一个作用域里由函数表达式定义的变量 a
- var a;
-
- // 在同一个作用域里由函数声明式赋值
- a = function () {
- alert(2);
- };
-
- // 在同一个作用域里由函数表达式赋值
- a = function () {
- alert(1);
- };
-
- a();
4、函数声明式与判断语句
以上3点,在各个主流浏览器中解释的结果为一致。而函数声明式在判断语句中解释结果在火狐中不一致。如:
- try {
- a();
- } catch (e) {
- alert('a函数调用失败!');
- }
-
- if (1) {
- function a() {
- alert(1);
- }
- } else {
- function a() {
- alert(2);
- }
- }
这个例子,惟独在火狐浏览器中弹出了“a函数调用失败!”的结果。其实按照上述3点的标准来,这个例子可以改写成:
- // 在同一个作用域里由第1个函数声明式定义变量a
- var a;
-
- // 在同一个作用域里由第2个函数声明式定义变量a
- var a;
-
- // 在同一个作用域里由第1个函数声明式定义赋值a
- a = function () {
- alert(1);
- };
-
- // 在同一个作用域里由第2个函数声明式定义赋值a
- a = function () {
- alert(2);
- };
-
- try {
- a();
- } catch (e) {
- alert('a函数调用失败!');
- }
-
- if (1) {
- // 空代码
- } else {
- // 空代码
- }
也就是说,判断语句是虚拟的,判断与否,最后的结果都是2。而火狐浏览器的表现却意外的不一致,它的解析结果为:
- try {
- a();
- } catch (e) {
- alert('a函数调用失败!');
- }
-
- if (1) {
- // 在判断语句里特殊定义
- var a;
-
- // 在判断语句里赋值
- a = function () {
- alert(1);
- };
- } else {
- // 在判断语句里特殊定义
- var a;
-
- // 在判断语句里赋值
- a = function () {
- alert(1);
- };
- }
当然,上面例子仅仅是为了表明函数声明式在各个浏览器中的表现不一致现象,在日常的码代码过程中,应当尽量避免,函数声明式出现在判断语句或其他语句块中。当然函数表达式是不会有这个问题的,因为函数表达式是预先定义,后赋值的。