标准参考

函数声明和函数表达式

定义一个函数有两种途径:函数声明和函数表达式。

函数声明:
function Identifier ( FormalParameterList

opt

 ) { FunctionBody }
函数表达式:
function Identifier

opt

 ( FormalParameterList

opt

 ) { FunctionBody }

ECMAScript 根据上下文来区分函数声明和函数表达式,假设 "function test(){}" 是一个表达式的一部分,它就是一个函数表达式,否则它就是一个函数声明。

关于函数声明和函数表达式的更多信息,请参考 ECMAScript 规范 13 Function Definition 中的内容。

函数声明可以出现的位置

根据 ECMAScript 规范第 13 章 Function Definition 和第 14 章 Program 中的描述,函数声明只能出现在 Program(程序,即全局环境)或函数体内。

换句话说,函数声明不能出现在( 如 if、while 或 for 语句)中。

问题描述

Firefox 的 TraceMonkey 引擎对函数声明的处理与 ECMAScript 规范的要求不符,TraceMonkey 将块中的函数声明作为“函数语句”来处理。而其他浏览器的引擎仍将这类块中的函数声明当作该块之外的函数声明来解析。

造成的影响

对块语句中的函数声明的处理差异,将导致某些功能不能按照预期实现,甚至代码出错。

受影响的浏览器

Firefox  

问题分析

TraceMonkey 将块中的函数声明作为“函数语句”来处理。而其他浏览器的引擎仍将这类块中的函数声明当作该块之外的函数声明来解析。

分析以下代码:

function foo(){
if(window===parent){
function bar(){alert(1);}
}
else{
function bar(){alert(2);}
}
bar();
}
foo();

以上代码中,两个标识符相同的函数声明被放在了 if...else... 块中。这不符合规范的约定,但各引擎的处理办法并不相同。

TraceMonkey 将这种位于块内的函数声明解析为“函数语句”,因此仅能被执行到的那个“函数语句”会生效,而其他浏览器则将二者仍看作当前作用域的函数声明,即不论 if...else... 的哪个分支最终会被执行,后者始终会覆盖前者,作为函数体 foo 内的、标识符为 foo 的函数存在。

注:Firefox 中在 if...else... 中使用函数声明的解析方式,在 MDC 中也有描述,参见:Conditionally defining a function

假设以上代码的判断条件 window===parent 为 true,各浏览器下的输出结果,如下表所示:

Firefox 其他浏览器
1 2

ECMAScript 规范第 5 版 12 章中的 Note 部分提到,虽然有些实现可以将函数声明作为语句处理,但这是不提倡的。

注:本文部分内容参考了文章:命名函数表达式探秘 中的内容。

解决方案

将条件语句中的函数声明替换为函数表达式,如:

function foo(){
if(window===parent){
var bar=function(){alert(1);}
}
else{
var bar=function(){alert(2);}
}
bar();
}
foo();

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6
Chrome 4.0.302.3 dev
Safari 4.0.4
Opera 10.51
测试页面: ...
本文更新时间: 2010-07-09

关键字

函数声明 函数表达式 语句块 同名函数 Conditionally defining a function

转载

http://w3help.org/zh-cn/causes/SJ9002

Firefox 对条件判断语句块内的函数声明的处理与其他浏览器有差异的更多相关文章

  1. 前端笔记知识点整合之JavaScript(三)关于条件判断语句、循环语句那点事

      一.条件分支语句 条件分支语句,也叫作条件判断语句,就是根据某种条件执行某些语句,不执行某些语句. JS中有三种语法是可以表示条件分支的 1.1 if……else…… 条件分支的主力语法,这个主力 ...

  2. 前端笔记之JavaScript(三)关于条件判断语句、循环语句那点事

    一.条件分支语句 条件分支语句,也叫作条件判断语句,就是根据某种条件执行某些语句,不执行某些语句. JS中有三种语法是可以表示条件分支的 1.1 if……else…… 条件分支的主力语法,这个主力语法 ...

  3. puppet(3) 变量、数据类型、表达式、条件判断语句-if、case、selector、unless

    puppet(4) 变量.数据类型.表达式.条件判断语句-if.case.selector语句 puppet变量: 1.名称必须以$开头:赋值使用=,支持追加赋值+=: 2.每个变量都有两种引用格式: ...

  4. python学习_条件判断语句_if

    #条件判断语句(if)#语法:if条件表达式:语句# 代码块#执行流程:if语句在执行时,会先对条件表达式进行求值判断#如果为True,则执行if后面的语句#如果为False,则不执行#默认情况下,i ...

  5. [19/09/16-星期一] Python的运算符和条件判断语句

    一.运算符 (1)算术运算符  + 加法运算符(如果是两个字符串之间进行加法运算,则会进行拼串操作) a = 10 + 5  计算 a = 'hello' + ' ' + 'world' 拼串  - ...

  6. Interview----求 1+2+...+n, 不能用乘除法、for、while if、else、switch、case 等关键字以及条件判断语句 (A?B:C)

    题目描述: 求 1+2+...+n, 要求不能使用乘除法.for.while.if.else.switch.case 等关键字以及条件判断语句 (A?B:C). 分析: 首先想到的是写递归函数,但是遇 ...

  7. 求1+2+…+n,要求不能使用乘除法、for、while、if、else、s witch、case 等关键字以及条件判断语句(A?B:C)和不用循环/goto/递归输出1~100的10种写法

    来源:据说是某一年某个公司的面试题 题目:求1+2+…+n, 要求不能使用乘除法.for.while.if.else.s witch.case 等关键字以及条件判断语句(A?B:C) 分析:这题本来很 ...

  8. if条件判断语句的不同

    let number = ["a":1, "b":2, "c":3]; if let num = number["d"] ...

  9. shell编程基础(3)条件判断语句

    1,带参数的shellscript #this is program build 5.11 to test shell script ############ cxz ####### 5.11 ### ...

随机推荐

  1. R语言---热图的制作

    >install.packages("gplots") > library("gplots")> p <- data.frame(rea ...

  2. 【原创】通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

    这篇blog重点在解决问题,如果你对字符编码并不是特别了解,建议先看看 < [原创]通俗易懂地解决中文乱码问题(1) --- 跨平台乱码 >. 当然,如果只是针对解决这个Mysql插入报错 ...

  3. windows服务删除后,在次安装时无法安装启动。

    当我在windows的cmd下卸载evtsys evtsys -u  再次安装时evtsys.exe -i -h 192.168.32.12 -p 514 提示“指定的服务已标记为删除”,进入服务管理 ...

  4. shell查找匹配行,输出该行并输出下面的一行

    查找匹配行,输出该行并输出下面的一行 grep: grep -A 1 'keyword'   file awk:awk '$0~/keyword/{print $0; getline; print $ ...

  5. ViewState压缩技术

    ViewState 的使用,大家可以说是又爱又恨,它其中一个特性就是保存页面的状态,对于只是展示的页面,我们可以直接在页面文件中使用 EnableViewState="false" ...

  6. 在DirectX 中进行2D渲染

    http://flcstudio.blog.163.com/blog/static/756035392008115111123672/ 最近,我看到很多关于DirectX8在最新的API中摒弃Dire ...

  7. IE下easyui 缓存问题

    $.ajaxSetup ({   cache: false //关闭AJAX相应的缓存 }); 这一句话就足够了,很管用!

  8. C#分页类

    using System.Linq; using System.Collections.Generic; namespace CommonLibrary { public class PagedLis ...

  9. 【笨嘴拙舌WINDOWS】消息机制

    如果将WINDOWS比做一个人,那么他就是为你提供各种服务的巫师,他手上有各式各样,奇形怪状的奇葩物品.他脑子充满了智慧,能够为你解决你所不能解决的疑难杂症.但是他不认识你! 你从小立志要想考状元,去 ...

  10. codeforces 510 C Fox And Names【拓扑排序】

    题意:给出n串名字,表示字典序从小到大,求符合这样的字符串排列的字典序 先挨个地遍历字符串,遇到不相同的时候,加边,记录相应的入度 然后就是bfs的过程,如果某一点没有被访问过,且入度为0,则把它加入 ...