javascript的语法作用域你真的懂了吗

有段时间没有更新了,思绪一下子有点转不过来。正应了一句古话“一天不读书,无人看得出;一周不读书,开始会爆粗;一月不读书,智商输给猪。”。再加上周五晚上看了下很久没看的湖南综艺节目《天天向上》关于出版书及读书的相关内容,看到相当多的嘉宾家里的书房让我惊叹也伴随着一种文人的向往。我虽然小的时候不太爱看书,但是随着自己一点点的长大,也不知道什么时候开始也有买书藏书看书的情节,而且正如郁钧剑老师所说的藏书有点会上瘾,即使有些书不是马上就会看。挺希望以后不工作了,有自己的一间书屋,一方书桌,一把椅子,一壶茶水,悠然自得的读书练习书法。

话题有点跑题了,切换模式回到这篇博客上来。在一次小组同事间分享的时候,有位同事给出了这样一个代码:


if (true) {
function fn() {
alert(‘为 true 时执行我!‘);
}
} else {
function fn() {
alert(‘为 false 时执行我!‘);
}
}
fn()

大家可以看下,这段代码执行的结果到底是什么?开启你智慧的大脑吧!

好吧,下面是各主流浏览器的执行结果:

  1. 最爱的chrome:// 为 false 时执行我!

  2. 不用很久的firefox // 为 true 时执行我!

  3. 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. 相同级别的语法作用域可以相互嵌套

  2. 高级别的语法作用域能够包含低级别的语法作用域

  3. 低级别的语法作用域不包含高级别的语法作用域。由于不存在包含关系,因此语言实现时,一般处理成语法的违例,或者理解为“平行”的关系。

规则一的示例:


/**
* 规则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的语法作用域你真的懂了吗,布布扣,bubuko.com

时间: 2024-12-03 05:03:22

javascript的语法作用域你真的懂了吗的相关文章

理解javascript原型和作用域系列(2)——函数和对象的关系

上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; console.log(fn instanceof Object); // true 对!函数是一种对象,但是函数却不像数组一样——你可以说数组是对象的一种,因为数组就像是对象的一个子集一样.但是函数与对象之间,却不仅仅是一种包含和被包含的关系,函数和对象之间的关系比较复杂,甚至有一点鸡生蛋蛋生鸡的逻辑

【翻译】JavaScript中的作用域和声明提前

原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执行结果是什么吗? 1 var foo=1; 2 function bar(){ 3 if(!foo){ 4 var foo=10; 5 } 6 alert(foo); 7 } 8 bar(); 如果你对弹出的结果是"10"感到惊讶的话,那么下面这段脚本会让你晕头转向的: 1 var a=1

理解javascript原型和作用域系列 - 目录【连载中...】

说明: 该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分——原型和作用域,当然,肯定少不了原型链和作用域链.帮你揭开javascript最神秘的面纱. 为什么要偏偏要讲这两个知识点? 这是我在这么多年学习javascript的经历中,认为最难理解.最常犯错的地方,学习这两个知识点,会让你对javascript有更深层次的理解,至少理解了原型和作用域,就不能再算是javascript菜鸟了.另外,这

你真的懂 ajax 吗?

前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库:damonare的ajax库 原文博客地址:你真的懂ajax吗? 知乎专栏&&简书专题:前端进击者(知乎)&&前端进击者(简书) 博主博客地址:Damonare的个人博客 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志. 正文 相信每个前端程序员日常工作中都避免不了的工作就是

javascript基础语法——变量和标识符

显示目录 目录 [1]定义 [2]命名规则 [3]声明[4]特性[5]作用域[6]声明提升[7]属性变量 前面的话 关于javascript,第一个比较重要的概念是变量,变量的工作机制是javascript的基本特性.实际上,变量是标识符的一种.本文将详细介绍变量和标识符 定义 标识符(Identifier)就是一个名字,用来对变量.函数.属性.参数进行命名,或者用做某些循环语句中的跳转位置的标记 //变量 var Identifier = 123; //属性 (new Object).Iden

理解javascript原型和作用域系列(8)——简述【执行上下文】

什么是“执行上下文”(也叫做“执行上下文环境”)?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时,已经知道了a是undefined,但却不知道a是10(第三句中). 在一段js代码拿过来真正一句一句运行之前,浏览器已经做了一些“准备工作”,其中就包括对变量的声明,而不是赋值.变量赋值是在赋值语句执行的时候进行的.可用下图模拟: 这是第一种情况. 下面还有.先来个简单的. 有js开发经验的朋友应该

理解javascript原型和作用域系列(5)——instanceof

又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/function,你不知道它到底是一个object对象,还是数组,还是new Number等等. 这个时候就需要用到instanceof.例如: 上图中,f1这个对象是被Foo创建,但是“f1 instanceof Object”为什么是true呢? 至于为什么过会儿再说,先把instanceof判

关于“javascript变量的作用域”的理解

*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin: 15px 0; } /* HEAD

javascript函数以及作用域简介

javascript函数以及作用域简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.基本函数 对于JavaScript中函数参数,实际参数的个数可能小于形式参数的个数,函数内的特殊值arguments中封装了所有实际参数.JavaScript中函数基本上可以分为以下三类: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8&