前言:最近恰逢毕业季,千千万万的学生党开始步入社会,告别象牙塔似的学校生活。往往在人生的各个拐点的时候,情感丰富,感触颇深,各种对过去的美好的总结,对未来的展望。与此同时,也让诸多的老“园”工看完这些小年轻的文章后感触良多,不禁也要写上几笔,所以就出来了很多类似“毕业两年小记”、“毕业五年有感”……

  可能就是某篇博文的一句话,某碗心灵鸡汤就拨动了你心里的那根尘封已久的弦,让你情不自禁的点了个赞,还忍不住的要在下面评论区留下自己此刻心潮澎湃的印记。

  我今天不是来送鸡汤的,鸡汤虽好,可不要贪杯哦。

正文

  截止上一篇关于Javascript的博文《初探JavaScript(三)——JS带我"碰壁"带我飞》已经写了三篇。前三篇主要是从一名纯小白的角度,结合《Javascript DOM编程艺术》这本书记录下自己的一些总结和感悟。

  大致的翻完《Javascript DOM编程艺术》后,感觉自己了解肯定还是太浅了,因为当时对于”原型”、”闭包”等这些完全没概念,我知道我缺的还很多。于是,我又伸出双手,接过另外一部经典之作《Javascript权威指南》,继续Javascript之行。

  今天首先介绍下Javascript的函数作用域的概念,然后了解下什么是作用域和声明提前,最后通过一个例子剖析Javascript的作用域链。

1.变量的作用域

  稍微有些编程背景的都知道,变量的作用域分为两种:全局变量局部变量

  Javascript是一门弱类型语言。所有的变量声明都是通过var来接收,如

var num = 1;
var str = “string”;
var flag = true;

  

  看似是一个非常省事的机制,但是也有让人头疼的时候,一些隐式的类型转换经常会把搞晕,这里不做展开,后面有时间可以单独开一篇详谈。先看看全局变量和局部变量:

var g = "global";
function f(){
var l = "local";
}

  

注意1.如果在函数f()中将去掉var声明,则变量l就会从局部变量升级为全局变量。

    2.局部变量的优先级高于同名的全局变量。如果在函数f()中声明一个局部变量也为g,则全局变量就会被局部变量覆盖

2.作用域和声明提前

  看到Javascript作用域这块,可以说颠覆了以前我对作用域的认识。类似Java和C等编程语言,在花括号“{}”内的代码都是有各自的作用域的,并且在这个范围以外,这些变量是不可见的,我们称这种作用域为块级作用域

  但是这完全不适用于Javascript,因为Javascript没有块级作用域,但是Javascript有函数作用域。函数作用域简言之就是:变量在声明他们的函数体以及这个函数体嵌套的任意函数体内都是有定义的

  对于“变量在声明他们的函数体以及这个函数体嵌套的任意函数体内都是有定义的”这句话的延伸理解:变量在声明之前就已经可用。我们称这种特性为声明提前,也就是函数里的所有变量都被“提前”至函数体的顶部

下面我们看一个经典的陷阱案例:

var v = "yoyo";
(function(){
console.log(v);
var v = "check now";
console.log(v);
})();

  

  对于第二次执行结果“check now”没有什么特别的,为什么第一次输出的不是“yoyo”而是“undefined”。

  对于这个问题的解释就用到上面的那句话,局部变量在整个函数体始终是有定义的,即在函数体内局部变量覆盖了同名全局变量,而且,程序只有在执行到var语句时,局部变量才会被真正赋值。所以,这时你大概会明白为什么是undefined了,因为此时还没有遇到var,即没有定义,等价于下面的形式:

var v = "yoyo";
(function(){
var scope;
console.log(v);
var v = "check now";
console.log(v);
})();

  

疑问???

将上面的代码稍稍修改为:

var v = "yoyo";
(function(){
console.log(v);
})();

  运行结果为:

  相比于上面的代码只是少了一行添加一个局部变量v并赋值的语句,但是结果却是“yoyo”。

  这里之所以输出“yoyo”,不能按照上面的定式思维。上面有句话叫“局部变量在整个函数体始终是有定义的”,但是这里没有局部变量的定义,所以按照下面要提到的作用域链会逐层向上寻找变量,最后找到了全局变量v,从而最后的输出是“yoyo”。

  以上是我的个人理解,如果你对这两种情况有自己的理解,请在下方给出,望不吝指教。

3.作用域链

  全局变量在程序中始终是有定义的局部变量在声明它的函数体内以及其所嵌套的函数内始终是有定义的

  每一段Javascript代码(全局代码或函数)都有一个与之相关联的作用域链,这个作用域链就是一个对象列表或链表。比如当Javascript需要查找变量x的值时,它会从链中的第一个对象开始,如果该对象有一个名为x的属性,则直接使用,如果不存在名为x的属性,则会继续向链上的下一个对象查找,如此递归下去直到找到。如果整个链上都找不到,则认为不存在x这个属性。举例:

name="lwy";
function t(){
var name="tlwy";
function s(){
var name="slwy";
console.log(name);
}
function ss(){
console.log(name);
}
s();
ss();
}
t();

  

  本文链接:《初探JavaScript(四)——作用域链和声明提前》 

  如果对你有用,欢迎点赞^_^

友情赞助

如果你觉得博主的文章对你那么一点小帮助,恰巧你又有想打赏博主的小冲动,那么事不宜迟,赶紧扫一扫,小额地赞助下,攒个奶粉钱,也是让博主有动力继续努力,写出更好的文章^^。

    1. 支付宝                          2. 微信

                      

初探JavaScript(四)——作用域链和声明提前的更多相关文章

  1. javascript篇-----函数作用域,函数作用域链和声明提前

    在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...

  2. JavaScript系列----作用域链和闭包

    1.作用域链 1.1.什么是作用域 谈起作用域链,我们就不得不从作用域开始谈起.因为所谓的作用域链就是由多个作用域组成的.那么, 什么是作用域呢? 1.1.1作用域是一个函数在执行时期的执行环境. 每 ...

  3. 从零开始讲解JavaScript中作用域链的概念及用途

    从零开始讲解JavaScript中作用域链的概念及用途 引言 正文 一.执行环境 二.作用域链 三.块级作用域 四.其他情况 五.总结 结束语 引言 先点赞,再看博客,顺手可以点个关注. 微信公众号搜 ...

  4. 理解JavaScript的作用域链

    上一篇文章中介绍了Execution Context中的三个重要部分:VO/AO,scope chain和this,并详细的介绍了VO/AO在JavaScript代码执行中的表现. 本文就看看Exec ...

  5. 从函数作用域和块级作用域看javascript的作用域链

    在ES6之前,javascript只有全局作用域和函数作用域.所谓作用域就是一个变量定义并能够被访问到的范围.也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这 ...

  6. 理解JavaScript中作用域链的关系

    javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则是prototype.proto和constructor的三角关系 ...

  7. javascript 之作用域链-07

    复习作用域 上一节我们说到作用域:是指变量可以访问的范围,他规定了如何查找变量,以及确定当前执行代码对变量的访问权限:也说到静态作用域即词法作用域,是在编译阶段决定变量的引用(由程序定义的位置决定,和 ...

  8. javascript 之作用域链-10

    前言 在<执行环境>文中说到,当JavaScript代码执行一段可执行代码时,会创建对应的执行上下文(execution context). 变量对象(Variable object,VO ...

  9. JavaScript的作用域链

    /* js当中 每个函数都是一个执行环境 函数调用函数会进入新的执行环境结束之后再回来当前 作用域链: 在内部的作用域中可以访问和修改外部的变量 在外部作用域不能修改或者访问内部的变量 */ var ...

随机推荐

  1. 去掉tableview cell的左边间隙问题

    http://www.jianshu.com/p/ba32f45222e0 简书上面的一篇文章.

  2. 从RAM新建QIcon对象 / Create a QIcon from binary data

    一般,QIcon是通过png或ico等图标文件来初始化的,但是如果图标资源已经在内存里了,或者一个zip压缩文件内,可以通过QPixmap作为桥梁,转换为图标. zf = zipfile.ZipFil ...

  3. Linux下安装tomcat

    安装tomcat之前首先安装jdk,这个看前面的帖子. 下面说centeros6.5安装tomcat7的方法: 1.将apache-tomcat-7.0.29.tar.gz文件上传到/home/zha ...

  4. 记一次troubleshooting(一):奇慢的脚本

    背景: 事情发生的时间是几年前,那时刚从windows server运维的部门调动过来,对linux和数据库还是处于一知半解的状态. 领导找过来说:前任遗留下来的问题你来调查一下,有个客户说他们的日次 ...

  5. Linux系统中如何挂载第二块硬盘

    一.检测硬盘能否被识别 # fdisk -l Disk /dev/sda: 36.7 GB, 36703934464 bytes 255 heads, 63 sectors/track, 4462 c ...

  6. Python黑客编程2 入门demo--zip暴力破解

    Python黑客编程2 入门demo--zip暴力破解 上一篇文章,我们在Kali Linux中搭建了基本的Python开发环境,本篇文章为了拉近Python和大家的距离,我们写一个暴力破解zip包密 ...

  7. Github教程(0)

    Git下载:https://git-for-windows.github.io/ 我下载的版本是:Git-2.6.3-64-bit.exe 安装:略 默认选项点击"下一步"即可 安 ...

  8. 如何基于纯GDI实现alpha通道的矢量和文字绘制

    今天有人在QQ群里问GDI能不能支持带alpha通道的线条绘制? 大家的答案当然是否定的,很多人推荐用GDI+. 一个基本的图形引擎要包括几个方面的支持:位图绘制,文字绘制,矢量绘制(如矩形,线条). ...

  9. 图文详解Unity3D中Material的Tiling和Offset是怎么回事

    图文详解Unity3D中Material的Tiling和Offset是怎么回事 Tiling和Offset概述 Tiling表示UV坐标的缩放倍数,Offset表示UV坐标的起始位置. 这样说当然是隔 ...

  10. 为什么占位符可以防止sql注入?

    先看下面用占位符来查询的一句话 String sql = "select * from administrator where adminname=?"; psm = con.pr ...