javascript的语法作用域你真的懂了吗
有段时间没有更新了,思绪一下子有点转不过来。正应了一句古话“一天不读书,无人看得出;一周不读书,开始会爆粗;一月不读书,智商输给猪。”。再加上周五晚上看了下很久没看的湖南综艺节目《天天向上》关于出版书及读书的相关内容,看到相当多的嘉宾家里的书房让我惊叹也伴随着一种文人的向往。我虽然小的时候不太爱看书,但是随着自己一点点的长大,也不知道什么时候开始也有买书藏书看书的情节,而且正如郁钧剑老师所说的藏书有点会上瘾,即使有些书不是马上就会看。挺希望以后不工作了,有自己的一间书屋,一方书桌,一把椅子,一壶茶水,悠然自得的读书练习书法。
话题有点跑题了,切换模式回到这篇博客上来。在一次小组同事间分享的时候,有位同事给出了这样一个代码:
if (true) {
function fn() {
alert('为 true 时执行我!');
}
} else {
function fn() {
alert('为 false 时执行我!');
}
}
fn()
大家可以看下,这段代码执行的结果到底是什么?开启你智慧的大脑吧!
好吧,下面是各主流浏览器的执行结果:
- 最爱的chrome:// 为 false 时执行我!
- 不用很久的firefox // 为 true 时执行我!
- IE7/8/9 // 为 false 时执行我!
哦,这是why?其实当我那同事问我们的时候,我的第一直觉就是 “为 true 时执行我!”。 后来,我想了想这个情况是不是浏览器在解析javascript的语法分析的时候有区别。
下面是我当时的猜想,大家不要当作是解释以上代码的理由:
1.chrome和IE在解析上述代码的时候语法作用域解析的变量与函数声明提升。大概是这样的意思:
function fn() {
alert('为 true 时执行我!');
}
function fn() {
alert('为 false 时执行我!');
} if (true) {
function fn() {
alert('为 true 时执行我!');
}
} else {
function fn() {
alert('为 false 时执行我!');
}
}
fn()
所以后面的函数覆盖前面的函数,所以才会是这样的结果。
firefox的解析可能不太一样,在处理语法作用域的时候,当函数声明的时候在if语句中是按顺序执行。
哈哈,以上也是自己的猜想,没有去研究浏览器之间的源码,能力有限,今日记下,日后有能 力再补上。也欢迎各路高手留言指点迷津。
分割,在我那个同事分享后放假就是五一,三天假期像我这样的宅男只能看着别人带着女朋友到处旅游;自个默默的只好宅在家里,三天休息也不是一点没有收获。三天有两天下午到公园跑步跑6圈,不经常跑步,一跑起来真是上气不接下气,但还是坚持跑完了自己定下的6圈,毕竟做程序的没有个好身体怎么行是吧?每晚,看会周爱民写的《javascript语言精髓与编程实践》,刚好看到模块化的层次---语法作用域这一节,就有涉及上述代码的解释。
javascript语法作用域图表:
特殊作用运算符图
在这一节的语法作用域之间的相关性是这样描述的:
结构化语言中,代码块的作用域是相互不相交的。这些作用域之间只存在平行或嵌套两种相关性。
例如:
代码平行:
/**
* 示例1:代码一与代码二平行
*/ // 代码一
if (true){
// ...
}
// 代码二
while (true) {
// ...
}
代码嵌套:
/**
* 示例2: 代码一与代码二嵌套
*/ // 代码一
if (true){
// ...
// 代码二
while (true) {
// ...
}
}
结构化语言是通过代码块这种“互不相交”的特性来保证逻辑上的独立,消除代码块之间的耦合。但是“嵌套”这种相关性中,代码二与代码一的语法作用域存在重叠。这种关系,就是通过前面所说的“语法作用域的级别”来控制。
- 相同级别的语法作用域可以相互嵌套
- 高级别的语法作用域能够包含低级别的语法作用域
- 低级别的语法作用域不包含高级别的语法作用域。由于不存在包含关系,因此语言实现时,一般处理成语法的违例,或者理解为“平行”的关系。
规则一的示例:
/**
* 规则1: 相同级别的代码的嵌套
*/
function fn1() {
function fn2() {
function fn3() {
// ....
}
}
}
规则二的示例:
/**
* 规则2: 高级别代码的嵌套低级别代码
*/
function fn1() {
if (true) {
// ...
}
}
规则三的示例:
/**
* 规则3: 低级别代码的嵌套高级别代码
*/
if (true) {
function fn1() {
// ...
}
} else {
function fn1() {
// ...
}
} // 低级别代码不能包含高级别代码,所以把这种嵌套关系理解成平行关系 if (true) {
// ..
} else {
// ...
} function fn1() {
// ...
} function fn1() {
// ...
} // 同名函数,后者覆盖前者
至此,大家看到规则三的时候是不是很眼熟啊,的确,看到这示例就很快能理解之前我同事分享那段代码在chrome和IE的执行结果是怎么一回事。
不过遗憾的是,没能解释为什么在firefox的执行原理,正如我前面个人的猜想的那样吧,只不过目前自己还没弄清在firefox的执行原理,不过那是迟早的事儿。还是那句话,欢迎大家不要吝惜自己的留言,把自己理解的分享给大家也是在提升自己。^_^!!!
javascript的语法作用域你真的懂了吗的更多相关文章
- 【翻译】JavaScript中的作用域和声明提前
原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...
- JavaScript中的作用域和声明提前
[翻译]JavaScript中的作用域和声明提前 原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译 ...
- 【repost】JavaScript 基本语法
JavaScript 基本语法,JavaScript 引用类型, JavaScript 面向对象程序设计.函数表达式和异步编程 三篇笔记是对<JavaScript 高级程序设计>和 < ...
- javascript变量的作用域
javascript变量的作用域 基本类型和引用类型 基本类型值指的是简单的数据段,而引用类型值指的是那个可能由多个值组成的对象 讲一个值赋值给变量时,javascript解析器首先要确定是基本类型 ...
- JavaScript中的作用域
很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...
- javascript笔记:javascript的关键所在---作用域链
javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...
- javascript基础语法——变量和标识符
× 目录 [1]定义 [2]命名规则 [3]声明[4]特性[5]作用域[6]声明提升[7]属性变量 前面的话 关于javascript,第一个比较重要的概念是变量,变量的工作机制是javascript ...
- JavaScript的语法要点 2 - Scope Chain
前文所述,JavaScript是基于词法作用域(lexically scoped)的,所以标识符被固定在它们被定义的作用域而不是语法上或是其被调用时的作用域.即全局变量的作用域是整个程序,局部变量的作 ...
- JavaScript的语法要点 1 - Lexically Scoped Language
作为从一开始接触C.C++.C#的程序员而言,JavaScript的语法对我来说有些古怪,通过最近一年的接触,对它有了一定的了解,于是想把它的一些语法要点记录下来. 1. Block Scope vs ...
随机推荐
- PC2日记——坑爹的第一天2014/08/28
我不想安慰自己说今天是因为第一次将pc2用于实际的比赛经验不足而导致的今天出现种种问题,我想说的是自从我開始干后台我所做的每一件事都是第一次,所以这绝对不是让自己免去责怪的理由:我想说的是假设我今天是 ...
- 21个js 技巧收藏
1 Javascript数组转换为CSV格式 首先考虑如下的应用场景,有一个Javscript的字符型(或者数值型)数组,现在需要转换为以逗号分割的CSV格式文件.则我们可以使用如下的小技巧,代码如 ...
- Linux 环境下 Lua 安装(转)
系统环境:CentOS-6.2-x86_64. Lua 是嵌入式脚本语言,应用场景很广泛. 引自官网:Lua is used in many products and projects around ...
- 玩转Web之easyui(二)-----easy ui 异步加载生成树节点(Tree),点击树生成tab(选项卡)
关于easy ui 异步加载生成树及点击树生成选项卡,这里直接给出代码,重点部分代码中均有注释 前台: $('#tree').tree({ url: '../servlet/School_Tree?i ...
- 探索WebKit核心(一)------ 新秀开始
为什么WebKit 现在,研究人员WebKit越来越多的人,我不能逃脱,其中还增加.WebKit也多亏了流行的浏览器和WebOS乱斗.随着Palm WebOS, Chrome OS, Firefox ...
- sqlite3触发器的使用
研究了一下osx下dock中应用的存储,位于~/Library/Application Support/Dock/下一个比較名字比較长的db文件里,之前简单的介绍过osx launchpad图标的删除 ...
- docker-gitlab(转)
Issues Docker is a relatively new project and is active being developed and tested by a thriving com ...
- 调整CentOS的文字登陆界面的分辨率
通过文字界面登陆到系统,切换到root权限. 用vi打开 /boot/grub/menu.lst 文件 ,因为menu.lst是grub.conf文件的快捷方式,终于打开的还是grub.conf文 ...
- IOS使用Jenkins持续集成
本文详细介绍了开发过程,提高效率进行IOS-Jenkins持续集成. 第二http://blog.csdn.net/monkey_cool/article/details/43270885 背景 平时 ...
- 【足迹C++primer】48、函数引用操作符
函数引用操作符 struct absInt { int operator()(int val) const { cout<<val<<"<->!!!&qu ...