初探JavaScript(四)——作用域链和声明提前
前言:最近恰逢毕业季,千千万万的学生党开始步入社会,告别象牙塔似的学校生活。往往在人生的各个拐点的时候,情感丰富,感触颇深,各种对过去的美好的总结,对未来的展望。与此同时,也让诸多的老“园”工看完这些小年轻的文章后感触良多,不禁也要写上几笔,所以就出来了很多类似“毕业两年小记”、“毕业五年有感”……
可能就是某篇博文的一句话,某碗心灵鸡汤就拨动了你心里的那根尘封已久的弦,让你情不自禁的点了个赞,还忍不住的要在下面评论区留下自己此刻心潮澎湃的印记。
我今天不是来送鸡汤的,鸡汤虽好,可不要贪杯哦。
正文
截止上一篇关于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(四)——作用域链和声明提前的更多相关文章
- javascript篇-----函数作用域,函数作用域链和声明提前
在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...
- JavaScript系列----作用域链和闭包
1.作用域链 1.1.什么是作用域 谈起作用域链,我们就不得不从作用域开始谈起.因为所谓的作用域链就是由多个作用域组成的.那么, 什么是作用域呢? 1.1.1作用域是一个函数在执行时期的执行环境. 每 ...
- 从零开始讲解JavaScript中作用域链的概念及用途
从零开始讲解JavaScript中作用域链的概念及用途 引言 正文 一.执行环境 二.作用域链 三.块级作用域 四.其他情况 五.总结 结束语 引言 先点赞,再看博客,顺手可以点个关注. 微信公众号搜 ...
- 理解JavaScript的作用域链
上一篇文章中介绍了Execution Context中的三个重要部分:VO/AO,scope chain和this,并详细的介绍了VO/AO在JavaScript代码执行中的表现. 本文就看看Exec ...
- 从函数作用域和块级作用域看javascript的作用域链
在ES6之前,javascript只有全局作用域和函数作用域.所谓作用域就是一个变量定义并能够被访问到的范围.也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这 ...
- 理解JavaScript中作用域链的关系
javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则是prototype.proto和constructor的三角关系 ...
- javascript 之作用域链-07
复习作用域 上一节我们说到作用域:是指变量可以访问的范围,他规定了如何查找变量,以及确定当前执行代码对变量的访问权限:也说到静态作用域即词法作用域,是在编译阶段决定变量的引用(由程序定义的位置决定,和 ...
- javascript 之作用域链-10
前言 在<执行环境>文中说到,当JavaScript代码执行一段可执行代码时,会创建对应的执行上下文(execution context). 变量对象(Variable object,VO ...
- JavaScript的作用域链
/* js当中 每个函数都是一个执行环境 函数调用函数会进入新的执行环境结束之后再回来当前 作用域链: 在内部的作用域中可以访问和修改外部的变量 在外部作用域不能修改或者访问内部的变量 */ var ...
随机推荐
- PHP 计算每个月的最后一天
主要用到了 PHP 的 date() 函数和 mktime() 函数. date() 函数的 format 参数用到了选项 t,它表示某个月总共有多少天,数值范围为28-31. mktime() 函数 ...
- SQL TRACE
1.SQL TRACE说明: 参数类型 布尔型 缺省值 false 参数类别 动态 取值范围 True|false 2.类型 1)sql trace参数:alter system改变对全局进程影响,如 ...
- Xamarin.Android中使用ResideMenu实现侧滑菜单
上次使用Xamarin.Android实现了一个比较常用的功能PullToRefresh,详情见:Xamarin. Android实现下拉刷新功能 这次将实现另外一个手机App中比较常用的功能:侧滑菜 ...
- 软件工程day4
使用ps制作了一个icon,将在下个版本中添加,用作程序图标. 参与组例会,得知新功能“吐槽墙”将以聊天室类似的社区形式实现. 提出对现有UI的建议: 对目前的登录窗口的UI不做改动,将标题的“用户登 ...
- Quartz.net 定时调度时间配置格式说明与实例
格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 1 秒 是 0-59 , - * / 2 分 是 0-59 , - * / 3 小时 ...
- EntityFunctions.AsNonUnicode
http://blog.csdn.net/zzx3q/article/details/7863797 使用工具VS2010 凡是调用FindAll的地方,如果传入参数是String类型的变量(数字类型 ...
- JavaScript思维导图—数组
JavaScript思维导图-来自@王子墨http://julying.com/blog/the-features-of-javascript-language-summary-maps/
- NSString NSUrl 相互转化
//NSString 转为 NSURL NSString *webStr = @"www.baidu.com"; NSURL *webUrl = [NSURL URLWithStr ...
- WebApi系列~通过HttpClient来调用Web Api接口~续~实体参数的传递
回到目录 上一讲中介绍了使用HttpClient如何去调用一个标准的Web Api接口,并且我们知道了Post,Put方法只能有一个FromBody参数,再有多个参数时,上讲提到,需要将它封装成一个对 ...
- 开发人员应该对IIS理论层的知识了解的多一些~第四讲 HttpModule中的几大事件
返回目录 本文主要介绍HttpModule,它在一个网页请求过程中是一个怎样的过程是我们要知道的,在网页加载过程中HttpModule在何时被执行也是我们要知道的,以及,HttpModule在网页请求 ...