JavaScript立即执行函数的解释分析(2)—函数表达式与函数声明的区别
说明
上次我们聊了聊表达式与语句的区别,这次我们说说函数表达式与函数声明,上次虽然提到过这两点,但是并没有很详细的讲,这次要专门聊聊了!
函数表达式(函数定义表达式)
函数定义表达式定义一个JavaScript函数。表达式的值就是这个新定义的函数。
比如,像这样
var a=function (x){ console.log(x) }
函数声明
说函数声明,就要提到上次我们说过的声明语句了,声明语句用来声明新变量或定义新函数,var和function都是声明语句,它们声明或定义变量或函数。 像这样
var i; //一个简单的变量
var j=2; //一个带有初始值的变量
function f(j){ return j+1;} //函数声明语句定义函数(函数声明)
区别
js程序在正式执行之前,会将所有 var 声明的变量和 function 声明的函数,预读到所在作用域的顶部,var 声明只是将声明提前,赋值仍然保留在原位置,function 声明,会将函数名称和函数体都提前,这个过程也被叫做,“预解析”或者“预编译”。 代码
var a=function (){
console.log("a");
}
function a(){
console.log("b");
}
a();
上面这段代码会输出 a,根据上面提到的概念,代码其实是这样执行的
var a; //var 声明只是将声明提前,赋值仍然保留在原位置
function a(){ //function 声明,会将函数名称和函数体都提前
console.log("b");
}
a=function(){
console.log("a");
}
a();
所以,最后的结果就是 a 了,如果你对声明提前还是不太理解可以看这里 谈谈 JavaScript 中的 声明提前(hoisting) 好的我们继续说别的区别。
代码
var a=function a (){
console.log(1);
}();
//这段代码会输出1
function a (){
console.log(1);
}
a();
//这段代码会输出1
function a (){
console.log(1);
}();
//这段代码会报错,如图
也许你会奇怪,到底发什么了什么,还记得上次我们说的调用表达式吗? 调用表达式是一种调用(或者执行)函数或方法的语法表示。
f(0) //f是一个函数表达式
函数在定义的时候是不执行的,要执行的话就要调用函数,就是用 函数表达式 +(),来调用,所以你明白了,第一段代码后面直接写(),是因为它本来就是函数表达式,后面写(),那自然就是调用了,而第二段代码,是函数声明,所以用了 函数名+()来调用,函数名在这就是函数表达式,但是最后一段代码报错了,因为它不是函数表达式,是函数声明,所以不能用直接加()的方式调用。
最后我们再说一点,先看代码
var a=1;
function b(){
function a(){
}
console.log(a);
}
b();
console.log(a);
//最后输出什么
结果
最后会输出 函数a 和 1,可能有朋友会奇怪,函数a 为什么没有覆盖全局变量a,解释一下。
一条函数声明语句实际上声明了一个变量,并把一个函数对象赋值给它。 也就是说在函数b 中声明了一个变量 a,这个变量a,就是函数b中的一个局部变量,所以,它不会影响外面的全局变量a,但是要是改成下面这样就会影响了。
var a=1;
function b(){
a=function (){
}
console.log(a); //输出一个函数
}
b();
console.log(a); //输出一个函数
结果
因为这样,在函数b中,没有声明a,但是给它赋值了,就相当于在全局对象中创建一个a,但是全局对象中已经有a了,所以会覆盖原来a的值,所以最后会输出两次函数
总结
简单说,函数表达式与函数声明的区别主要是两个方面,一方面是声明提前的区别,虽然都提前,但函数表达式只是将声明提前,赋值仍然保留在原位置,函数声明,会将函数名称和函数体都提前,另一方面就是调用的区别,函数表达式后面可以直接写()来调用函数,而函数声明不可以。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 新型php漏洞挖掘之debug导致的安全漏洞(Edusoho)
- CVE-2016-3714 - ImageMagick 命令执行分析
- 知乎某处XSS+刷粉超详细漏洞技术分析
- 【STM32H7】第12章 RL-TCPnet V7.X之TCP客户端
- 【STM32F429】第12章 RL-TCPnet V7.X之TCP客户端
- Django DeleteView without confirmation template, but with CSRF attack
- 小记 TypeScript 中的循环引用问题
- 别只会搜日志了,求你懂点检索原理吧
- 分布式系统中的事务问题
- JDK 中的栈竟然是这样实现的?
- 谈一谈如何在Python开发中拒绝SSRF漏洞
- eval长度限制绕过 && PHP5.6新特性
- Cookie-Form型CSRF防御机制的不足与反思
- Python 格式化字符串漏洞(Django为例)
- unity官方案例精讲(第三章)--星际航行游戏Space Shooter