阅读 62

一个例子讲清楚函数声明和函数表达式

首先我们来了解一下函数声明与函数表达式的定义。

函数声明

一个标准的函数声明,由关键字function 、函数名、形参和代码块组成。
有名字的函数又叫具名函数

举个例子:

function quack(num) {
for (var i = 0; i < num; i++) {
  	console.log("Quack!")
  }
}
quack(3)
复制代码

函数表达式

函数没有名称,而且位于一条赋值语句右边,被赋给一个变量。
在语句(如赋值语句)中,以这样的方式使用关键function时,创建的是函数表达式。 
没有名称的函数又叫匿名函数

举个例子:

var fly = function(num) {
	for (var i = 0; i < num; i++) {
		console.log("Flying!");
	}
}
fly(3)
复制代码

无论你使用函数声明还是函数表达式,得到的都是函数。那么它们的区别何在呢?
仅仅是函数声明更方便,还是函数表达式有些独特之处使其很有用?
亦或是它们只是两种做相同事情的不同方式而已?

乍一看,函数声明和函数表达式差别不大,但实际上它们存在根本性差别。
要明白这种差别,首先需要研究一下浏览器在运行阶段如何处理代码。
下面我举个例子,看看浏览器如何分析并执行网页中的代码。

举例

var migrating = true;
var fly = function (num) {
  for (var i = 0; i < num; i++) {
  	console.log("Flying!")
  }
}

function quack(num) {
  for (var i = 0; i < num; i++) {
  	console.log("Quack!")
  }
}

if (migrating) {
  quack(4)
  fly(4)
}
复制代码

分析浏览器如何执行代码

第一步:分析函数声明
在分析网页期间(执行任何代码之前),浏览器查找函数声明。找到函数声明时,浏览器创建相应的函数,并将得到的函数引用赋给与函数同名的变量。

image.png

第二步:浏览器执行代码
处理所有的函数声明后,浏览器回到代码开头,开始按从头到尾的顺序执行代码。

image.png

第三步:继续执行
处理完变量fly后,浏览器继续往下执行。接下来的语句是函数quack的声明,因为已经处理过了,所以浏览器跳过声明,接着执行后面的条件语句。

image.png

我们来总结一下,浏览器的执行过程。

  1. 首先扫描代码,查找函数声明
  2. 分析函数声明(存储该函数,并创建一个与函数同名变量来存储指向该函数的引用)
  3. 处理完所有函数声明后,浏览器从头开始执行代码(按顺序处理各种函数变量)
  4. 碰到函数表达式时,同函数声明,需存储该函数,并将指向该函数的引用赋给表达式左边的变量

得出结论:函数声明与函数表达式的区别

函数声明 函数表达式
1 函数声明是完整的语句 函数表达式只是语句的一部分
2 函数命名时,创建一个与函数同名的变量,并让它指向函数 函数命名时,通常不给函数指定名称,因此需要在代码中将函数赋给一个变量,或以其他方式使用函数表达式
3 可出现在代码的任何地方,函数声明创建的函
数都是已定义的,这被称为提升 (hoisting)
函数表达式创建的函数要等到它执行后才被定义
4 函数将在执行代码前创建,即使未调用,也占用内存空间 函数将在运行阶段执行代码时临时创建,调用完,立即释放,所以更节省内存空间

后记

本文参考的相关文章:

  • 《Head First Javascript 程序设计》

由于本人水平有限,如有描述不准确的地方请给我留言,欢迎交流~
本文为个人原创,转载请注明出处。