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

news/2024/7/19 15:58:11 标签: 函数, 函数声明, js, 函数表达式, 函数定义

首先,我们来完成一些小测试:
test1:

js javascript">js-function">js-keyword">function js-title">foojs-params">(){
    js-function">js-keyword">function js-title">barjs-params">() {
        js-keyword">return js-number">3;
    }
    js-keyword">return bar();
    js-function">js-keyword">function js-title">barjs-params">() {
        js-keyword">return js-number">8;
    }
}
alert(foo());

test2:

js javascript">js-function">js-keyword">function js-title">foojs-params">(){
    js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">3;
    };
    js-keyword">return bar();
    js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">8;
    };
}
alert(foo());

test3:

js javascript">alert(foo());
js-function">js-keyword">function js-title">foojs-params">(){
    js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">3;
    };
    js-keyword">return bar();
    js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">8;
    };
}

test4:

js javascript">js-function">js-keyword">function js-title">foojs-params">(){
    js-keyword">return bar();
    js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">3;
    };
    js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">8;
    };
}
alert(foo());

答案:8、3、3、[Type Error: bar is not a function]

函数声明">什么是函数声明?

Function Declaration 可以定义命名的函数变量,而无需给变量赋值。Function Declaration 必须以“function”开头。

js javascript">js-function">js-keyword">function js-title">barjs-params">() {
    js-keyword">return js-number">3;
}

函数名在自身作用域和父作用域内是可获取的(否则就取不到函数了)。

js lua">   js-function">js-keyword">function js-title">barjs-params">() {
        js-keyword">return js-number">3;
    }

    alert(bar()); //js-number">3
    alert(bar)  //js-function">js-keyword">function js-title">barjs-params">(){js-keyword">return js-number">3;}

函数表达式">什么是函数表达式?

Function Expression 将函数定义为表达式语句(通常是变量赋值)的一部分。通过 Function Expression 定义的函数可以是命名的,也可以是匿名的。Function Expression 不能以“function”开头。

js javascript">js-comment">//anonymous function expression
js-keyword">var a = js-function">js-keyword">functionjs-params">() {
    js-keyword">return js-number">3;
}

js-comment">//named function expression
js-keyword">var a = js-function">js-keyword">function js-title">barjs-params">() {
    js-keyword">return js-number">3;
}

js-comment">//self invoking function expression
(js-function">js-keyword">function js-title">sayHellojs-params">() {
    alert(js-string">"hello!");
})();

函数名(如果有的话)在作用域外是不可获取的(与 Function Declaration 对比)。

那么它们有什么区别呢?

实际上,解析器在向执行环境加载数据是,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到执行到它所在的代码行,才会真正被解释执行。

现在来解释下前面的测试。

test1 用了 function declaration,也就是说它们 get hoisted(被提升了)

什么是 Hoisting?
这里引用 Ben Cherry的话:“Function declaration和function variable(函数变量)通常会被 JavaScript 解释器移(‘hoisted’)到当前作用域顶部”。

function declaration 被提升时,整个函数体都会随之提升,所以 test1 的代码经过解释器解释后是像这样运行的:

js javascript">js-comment">//**Simulated processing sequence for Question 1**
js-function">js-keyword">function js-title">foojs-params">(){
    js-comment">//define bar once
    js-function">js-keyword">function js-title">barjs-params">() {
        js-keyword">return js-number">3;
    }
    js-comment">//redefine it
    js-function">js-keyword">function js-title">barjs-params">() {
        js-keyword">return js-number">8;
    }
    js-comment">//return its invocation
    js-keyword">return bar(); js-comment">//8
}
alert(foo());

Function Expression 会被提升吗?

这取决于表达式。比如 test2 中的第一个表达式:

js javascript">js-keyword">var bar = js-function">js-keyword">functionjs-params">() {
    js-keyword">return js-number">3;
};

等号左边的(var bar)是 Variable Declaration。Variable Declaration 会被提升,但是 Assignment Expression(赋值表达式)不会。所以当 bar 提升时,解释器会这样初始化:var bar = undefined。而函数定义本身不会被提升。所以 test2 的代码经过解释器解释后是像这样运行的:

js javascript">js-comment">//**Simulated processing sequence for Question 2**
js-function">js-keyword">function js-title">foojs-params">(){
    js-comment">//a declaration for each function expression
    js-keyword">var bar = js-literal">undefined;
    js-keyword">var bar = js-literal">undefined;
    js-comment">//first Function Expression is executed
    bar = js-function">js-keyword">functionjs-params">() {
        js-keyword">return js-number">3;
    };
    js-comment">// Function created by first Function Expression is invoked
    js-keyword">return bar();
    js-comment">// second Function Expression unreachable
}
alert(foo()); js-comment">//3

test 3 和 test 1 的逻辑相似。这次是 foo 函数被提升了。
test 4 就很简单了,根本就没有函数提升……

js javascript">js-comment">//**Simulated processing sequence for Question 4**
js-function">js-keyword">function js-title">foojs-params">(){
    js-comment">//a declaration for each function expression
    js-keyword">var bar = js-literal">undefined;
    js-keyword">var bar = js-literal">undefined;
    js-keyword">return bar(); js-comment">//TypeError: "bar not defined"
    js-comment">//neither Function Expression is reached
}
alert(foo());

还应该注意什么?

官方是禁止在非功能模块(比如 if)中使用 Function Declaration 的。但是所有浏览器都支持,但是各自的解释方式不同。

例如下面的代码段在 Firefox 3.6 中会抛错,因为它将 Function Declaration 解释成了 Function Statement(见上文),所以 x 没有定义。但是在 IE8、Chrome 5 和 Safari 5 中,会返回函数 x(和标准的 Function Declaration 一样)。

js javascript">js-function">js-keyword">function js-title">foojs-params">() {
    js-keyword">if(js-literal">false) {
        js-function">js-keyword">function js-title">xjs-params">() {};
    }
    js-keyword">return x;
}
alert(foo());

http://www.niftyadmin.cn/n/764430.html

相关文章

pythonpandas设置索引_Python中pandas的层级索引!

1、认识层级索引以下示例将创建一个 Series 对象, 索引 Index 由两个子 list 组成,第一个子 list 是外层索引,第二个 list 是内层索引:>>> import pandas as pd>>> import numpy as np>>> obj pd.Ser…

js中递归实现的方法及其区别

递归函数&#xff1a;递归函数是在通过名字调用自身的情况下构成的。 递归实现阶乘函数&#xff1a; 方法一&#xff1a;通过使用函数的名字 function factorial(num){if(num<1){return 1;}else{return num*factorial(num-1);}}console.log(factorial(4)); 结果为&#x…

python通过句柄输入_python win32api win32gui win32con 窗口句柄 发送消息 常用方法 键盘输入...

import win32guiimport win32conimport win32api# 从顶层窗口向下搜索主窗口&#xff0c;无法搜索子窗口# FindWindow(lpClassNameNone, lpWindowNameNone) 窗口类名 窗口标题名handle win32gui.FindWindow("Notepad", None)# 获取窗口位置left, top, right, bottom…

学习javascript闭包

闭包&#xff1a;是指有权访问另一个函数作用域变量的函数。 创建闭包的常见方式就是在一个函数内创建另一个函数。 理解如何创建作用域链以及作用域链的用途对于理解闭包非常重要。作用域链本质上是一个指向变量对象的指针列表&#xff0c;它只引用但不实际包含变量对象。无…

python产品发布会_Python django框架开发发布会签到系统(web开发)

引言最近学习了虫师的发布会签到系统demo&#xff0c;结合自己所学django知识&#xff0c;对demo重新塑造了一下。也是为了练练手&#xff0c;巩固知识。现在就分享一下成果~Django工作流学习django web开发&#xff0c;先来简单了解一下django的工作机制&#xff0c;请看下图&…

javascript中的垃圾收集及内存泄漏

一、什么是内存泄漏&#xff1f; 程序的运行需要内存。只要程序提出要求&#xff0c;操作系统或者运行时&#xff08;runtime&#xff09;就必须供给内存。 对于持续运行的服务进程&#xff08;daemon&#xff09;&#xff0c;必须及时释放不再用到的内存。否则&#xff0c;内…

sessionstorage ie8下跨页面_初级会计报名注册不了,下一步无法操作怎么办?

又到了一年报名季&#xff0c;各种各样的报名问题纷沓而来&#xff0c;重重叠叠~今天&#xff0c;传知君为大家解答的是&#xff1a;初级会计报名注册不了&#xff0c;下一步无法操作怎么办&#xff1f;初级会计职称考试&#xff0c;传知网校从上方页面看&#xff0c;这位学员使…

javascript模仿块级作用域

javaScript 没有块级作用域的概念。这意味着在块语句中定义的变量&#xff0c;实际上是在包含函数中而非语句中创建的&#xff0c;来看下面的例子: function outputNumbers(count){for (var i0; i < count; i){alert(i);}alert(i); //计数 } 这个函数中定义了一个for 循环…