为什么if else 语句里不能用函数声明定义函数,而可以用函数表达式定义函数

在《JavaScript高级程序设计》第三版第7章函数表达式部分讲到,定义函数有两种方式:一种是函数声明,另一种就是函数表达式。函数声明的语法是这样的。
function functionName(arg0, arg1, arg2) {
//函数体
}

于函数声明,它的一个重要特征就是函数声明提升function declaration hoisting),意思是在执行代码之前会先读取函数声明。这就意味着可以把函数声明放在调用它的语句后面。
sayHi();
function sayHi(){
alert("Hi!");
}
这个例子不会抛出错误,因为在代码执行之前会先读取函数声明。

第二种创建函数的方式是使用函数表达式。函数表达式有几种不同的语法形式。下面是最常见的一种形式。
var functionName = function(arg0, arg1, arg2){
//函数体
};

这种形式看起来好像是常规的变量赋值语句,即创建一个函数并将它赋值给变量 functionName。
这种情况下创建的函数叫做匿名函数( anonymous function),因为 function 关键字后面没有标识符。(匿名函数有时候也叫拉姆达函数。)匿名函数的 name 属性是空字符串。
函数表达式与其他表达式一样,在使用前必须先赋值。以下代码会导致错误。
sayHi(); //错误:函数还不存在
var sayHi = function(){
alert("Hi!");
};
理解函数提升的关键,就是理解函数声明与函数表达式之间的区别。例如,执行以下代码的结果可能会让人意想不到。
//不要这样做!
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
表面上看,以上代码表示在 condition 为 true 时,使用一个 sayHi()的定义;否则,就使用另一个定义。实际上,这在 ECMAScript 中属于无效语法, JavaScript 引擎会尝试修正错误,将其转换为合
理的状态。但问题是浏览器尝试修正错误的做法并不一致。大多数浏览器会返回第二个声明,忽略condition; Firefox 会在 condition 为 true 时返回第一个声明。因此这种使用方式很危险,不应该
出现在你的代码中。不过,如果是使用函数表达式,那就没有什么问题了。

(为什么属于无效的语法呢?这要从词法作用来说,在《JavaScript语言精髓与编程实践》第3章3.2基本语法的结构化含义 ,其中3.2.2.2语法作用域的相关性这一小节回答了以上的疑问,

以下属于摘抄部分:

上面的代码function的语法作用比表达式的语法作用域高,所以上面if。。。else。。。语句不能包含函数的词法作用域,JavaScript会将其理解为“平行”的关系,即如下所示

本例中的代码也会理解为:

if(condition){}

else {}

function sayHi(){
alert("Hi!");
}

function sayHi(){
alert("Yo!");

相当于第二个sayHi()函数覆盖了第一个,所以会大多数浏览器会返回第二个声明,忽略condition。

当然书中也建议如下作:

//可以这样做
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
};
} else {
sayHi = function(){
alert("Yo!");
};
}
这个例子不会有什么意外,不同的函数会根据 condition 被赋值给 sayHi。

原文地址:https://www.cnblogs.com/menghome/p/9277855.html

时间: 2024-10-12 16:32:11

为什么if else 语句里不能用函数声明定义函数,而可以用函数表达式定义函数的相关文章

25.函数例题-预解析 作用域 、函数变量优先级、全局变量污染(直接在全局声明 、 函数里的变量没声明)但是函数里的变量没声明造成的全局变量污染有个前提,函数要被调用)

1.  return foo()   foo 没有return值,故为undefined.   2.      a b 在函数作用域内,外界找不到   var a = b =3; b 也算用var 声明了,只不过b 是在全局隐式var 了一个b ,在函数内部找不到变量的情况下就去全局找,全局找不到报错.    语法有错误,程序一句都不会执行,执行阶段有错误,会执行没错的代码,在执行出错的地方报错.  函数或则匿名函数体内声明变量是为了避免全局变量污染 重要例题:  函数没执行,全局没找到 b报错

C++函数声明和定义

声明是告诉编译器一些信息,以协助编译器进行语法分析,避免编译器报错.而定义是告诉编译器生成一些代码,并且这些代码将由连接器使用.即:声明是给编译器用的,定义是给连接器用的.这个说明显得很模糊,为什么非要弄个声明和定义在这搅和?那都是因为C++同意将程序拆成几段分别书写在不同文件中以及上面提到的编译器只从上朝下编译且对每个文件仅编译一次. 编译器编译程序时,只会一个一个源文件编译,并分别生成相应的中间文件(对VC就是.obj文件),然后再由连接器统一将所有的中间文件连接形成一个可执行文件.问题就是

[转] 函数声明和函数表达式——函数声明的声明提前

定义函数的方法 定义函数的方法主要有三种: 函数声明(Function Declaration) 函数表达式Function Expression) new Function构造函数 其中,经常使用的是函数声明和函数表达式的函数定义方法,这两种方法有着很微妙的区别和联系,而且这两种方法的使用也容易混淆,所以这篇文章主要总结下这两种函数定义方法的相关知识点,当然本文的主题依然是关于函数提前的. 函数声明的典型格式: function functionName(arg1, arg2, ...){ <

函数声明和函数表达式——函数声明的声明提前

写在前面的那些不得不说的废话 前两天班级聚会,除了吃喝玩乐就是睡觉扯淡,甚是喜悦,真是独乐乐不如众乐乐啊. PS:毕业的或即将毕业的有时间能聚就聚吧,毕了业以后属于自己的时间能聚到一块儿可就少太多了. 现在有点时间来看点东西总结些东西了,又因为前段时间片片断断地看了看JavaScript的函数部分,所以抽时间总结下函数的相关部分,当然,里面有些部分都是自己的理解,如果有理解的不对的地方还请小伙伴们不吝指出. 这一节我结合自己的理解和小伙伴们聊一下函数声明的声明提前. 注:有的地方也叫函数声明提升

【JavaScript】Javascript中的函数声明和函数表达式

Javascript有很多有趣的用法,在Google Code Search里能找到不少,举一个例子: <script> ~function() { alert("hello, world."); }(); </script> 试一下就知道这段代码的意思就是声明一个函数,然后立刻执行,因为Javascript中的变量作用域是基于函数的,所以这样可以避免变量污染,但这里的位运算符『~』乍一看让人摸不到头脑,如果去掉它再运行则会报错:SyntaxError. 在阐述

JS执行顺序-函数声明提升、匿名函数、函数表达式

大方向上: JS 是按照 代码块 进行 编译.执行 的. 学习至: 1.变量声明提升 2.新唐的博客 3.js中匿名函数的创建与调用方法分析 4.前端圣经 - 高程三 5.深入理解变量声明提升和函数声明提升 因为没有好好地分类.可能会比较杂.为了系统地学习,先了解几个概念. 一. <script> 区分的代码块. JS是按照代码块 编译 和 执行的.代码块间 相互独立,但是 变量和方法 共享. <script> alert('代码块一'); </script> <

js (JavaScript)函数声明的几种形式及用法

1.函数声明 语法: function functionName(parameters) { 执行的代码 } 函数声明后不会立即执行,只是在初始化的时候会将函数声明提升,会在我们需要的时候调用到. 2.函数表达式(匿名函数) 语法: var x = function (a, b) {return a * b};var z = x(4, 3); 以上函数实际上是一个 匿名函数 (函数没有名称). 函数存储在变量中,不需要函数名称,通常通过变量名来调用. 3.Function() 构造函数 通过内置

C++纯虚函数、虚函数、实函数、抽象类,重载、重写、重定义

首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不完全相同的新类,使用动态绑定,可以在一定程度上忽略相似类的区别,而以统一的方式使用它们的对象. 虚函数的作用是实现多态性(Polymorphism),多态性是将接口与实现进行分离,采用共同的方法,但因个体差异而采用不同的策略.纯虚函数则是一种特殊的虚函数.虚函数联系到多态,多态联系到继承. 一.虚函

函数声明和函数表达式

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 </head> 7 <body> 8 <script> 9 //函数表达式后面加括号可以直接执行: 10 //函数声明是需要被提前解析的 11 12 //函数表达式

c++ 函数声明 &amp; 分离式编译 &amp; 参数传递

p186~p188: 函数声明1.函数只能定义一次,但是可以声明多次. 2.函数的接口:返回类型 + 函数名 + 形参类型 3.为什么要在头文件中进行函数声明???在源文件中定义?暂时理解到,这么做可以增强可读性. 4.含有函数声明的头文件应该被包含到定义函数的源文件中.(例如:#include "diy.h") 分离式编译 & 6.8 & 6.9 1.分离式编译:把源文件割成好几块放在不同的文件夹下.最终要生成可执行文件,就必须告诉编译器源文件在哪里.具体操作如下: