Firefox 对条件判断语句块内的函数声明的处理与其他浏览器有差异
标准参考
函数声明和函数表达式
定义一个函数有两种途径:函数声明和函数表达式。
- 函数声明:
-
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 对条件判断语句块内的函数声明的处理与其他浏览器有差异的更多相关文章
- 前端笔记知识点整合之JavaScript(三)关于条件判断语句、循环语句那点事
一.条件分支语句 条件分支语句,也叫作条件判断语句,就是根据某种条件执行某些语句,不执行某些语句. JS中有三种语法是可以表示条件分支的 1.1 if……else…… 条件分支的主力语法,这个主力 ...
- 前端笔记之JavaScript(三)关于条件判断语句、循环语句那点事
一.条件分支语句 条件分支语句,也叫作条件判断语句,就是根据某种条件执行某些语句,不执行某些语句. JS中有三种语法是可以表示条件分支的 1.1 if……else…… 条件分支的主力语法,这个主力语法 ...
- puppet(3) 变量、数据类型、表达式、条件判断语句-if、case、selector、unless
puppet(4) 变量.数据类型.表达式.条件判断语句-if.case.selector语句 puppet变量: 1.名称必须以$开头:赋值使用=,支持追加赋值+=: 2.每个变量都有两种引用格式: ...
- python学习_条件判断语句_if
#条件判断语句(if)#语法:if条件表达式:语句# 代码块#执行流程:if语句在执行时,会先对条件表达式进行求值判断#如果为True,则执行if后面的语句#如果为False,则不执行#默认情况下,i ...
- [19/09/16-星期一] Python的运算符和条件判断语句
一.运算符 (1)算术运算符 + 加法运算符(如果是两个字符串之间进行加法运算,则会进行拼串操作) a = 10 + 5 计算 a = 'hello' + ' ' + 'world' 拼串 - ...
- 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). 分析: 首先想到的是写递归函数,但是遇 ...
- 求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) 分析:这题本来很 ...
- if条件判断语句的不同
let number = ["a":1, "b":2, "c":3]; if let num = number["d"] ...
- shell编程基础(3)条件判断语句
1,带参数的shellscript #this is program build 5.11 to test shell script ############ cxz ####### 5.11 ### ...
随机推荐
- ubuntu搭建svn、git遇到的问题及解决办法
不错的git笔记博客: http://www.cnblogs.com/wanqieddy/category/406859.html http://blog.csdn.net/zxncvb/articl ...
- Android eMMC Booting
Android eMMC Booting Contents [hide] 1 eMMC binaries 1.1 Creating the GPT table 1.2 Modifying .IMG F ...
- 短地址TinyURL的API使用
TinyURL的短地址服务超过10年了,很稳定,官方没有给出API连接,其实很简单: API: 调用:http://tinyurl.com/api-create.php?url=http://URL, ...
- 头文件中的#ifndef/#define/#endif 的作用
在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量重定义的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定 ...
- RIA技术
Rich Internet Application(富互联网应用程序,简称RIA),一种全新的Web应用程序架构,它结合了桌面软件良好的用户体验和web应用程序易部署的优点,很快获得了企业的青睐. 近 ...
- c#调用系统资源大集合-2
public static void 打开格式化对话框() { Process.Start("rundll32.exe"," shell32.dll,SHFormatDr ...
- IE6下margin出现双边距
在IE6下,块元素有浮动和横向margin的时候,横向的margin值会被放大成两倍 解决方法:添加display:inline; eg:下面的例子在IE6下会有两倍边距 <style> ...
- [转载]mysql的binlog安全删除
[转载]mysql的binlog安全删除 理论上,应该在配置文件/etc/my.cnf中加上binlog过期时间的配置项,expire_logs_days = 10 但是如果没有加这一项,随着产生越 ...
- Postgresql两表联结更新
Postgresql两表联合更新近日使用Postgresql感到有点不好用,一个联合更新非要这样写语法才对:update d_routetripset name=b.name , descrip ...
- window下python 扩展库安装 使用第三方镜像源
0.前言 由于python的官方镜像位于国外,若使用pip或者easy_install安装第三方插件时或许会被限制,甚至连easy_install或pip也无法安装,例如在windows环境下 ...