我所理解的javascript中函数的作用域和作用域链
http://www.cnblogs.com/zt-blog/p/6654308.html
写在前面
一周木有更新了,今天终于攻克了自行车难关,非常开心,特意来一更~ (那些捂嘴偷笑的人我看到你们了快把嘴闭上我会假装没看见)。
本文内容均基于个人理解,如有不认同,墙裂欢迎留言交流~~~
正文
作用域
简单来说,javascript中有变量和函数的声明/定义,有变量赋值和函数的执行 ,且遵循先声明后执行原则,举个例子:
var a = 1; // 表达式 function func(){ a = a + 1; }; // 函数声明 func(); // 函数执行
上面的代码等同于下面这个:
var a; // 变量声明 function func(){ a = a + 1; }; // 函数声明 a = 1; //执行变量赋值
func(); // 函数执行 --> a=2
理解了先声明后执行原则之后,再来看作用域部分。简单来说,javascript的作用域分两类,一类是最外层作用域,如javascript标签包裹起来的块,或者常见的包含init()的块,如下:
//html文件中 script标签包裹的块
<script>
...
</script> //外部 javascript文件中最外层的块,一般包含init()
function init(){ ... }
...
init()
另一类是当javascript碰到一个function时,这个function内部会形成一个它内部的作用域。如下:
/*相对于函数来说的作用域*/ ...
//这里是函数外部作用域
...
function(){
//这里是函数内部作用域
// ...
}
第一次敲桌子--内部作用域可以访问外部作用域的值,反之行不通!好了,知道了这两类作用域后,再来边举个栗子边梳理作用域这个东西,栗子如下:
var a = 1;
var b;
var c;
function f(){
b = 2;
var d = 3;
console.log(a); //1
console.log(b); //
console.log(d); //3
}
f();
console.log(a); //
console.log(b); //
console.log(c); //undefined
console.log(d); //报错: d is not defined
上面的栗子已经注释给出了结果,看到输入的结果觉得正常么?(我好像问了句废话。。。)我还是按照先声明后执行的原则来看下,首先,从上到下,声明了变量a,b,c,函数f,接着执行了a=1,执行函数f,这里第二次敲桌子啦敲桌子!!-- 执行f的时候发生了什么呢?不记得的翻上去看下,首次敲桌时说过了函数内部会形成新的内部的作用域。我们来看下这个作用域,首先声明d,然后执行b=2,d=3,console.log(a),第一次敲桌子的时候说了内部作用域可以访问外部作用域的值,so这里a输入为1,接下来b和d都在函数内部赋过值了,所以console.log(b)和console.log(d)分别输出2和3。至此,f已经执行完了(下划线这部分),继续,console.log(a)这里a也已经赋过值会输出1,console.log(b) -- 第三次敲桌子啦!!!--b声明在外部作用域,赋值在f内部作用域,那么这个赋值的结果在外部作用域还生效么?答案显而易见,生效的,输出2(因为外部声明了,这个变量就一直存在,其他地方的赋值对其均有效)。再然后console.log(c) -- 第四次敲桌子!!!!c只是声明了而已,并没有赋值,因此输出undefined。最后console.log(d) -- 第五次敲桌子!!!!!d为啥会报错呢?回头看首次敲桌时是怎么说的,“反之行不通”,即:函数外部不能访问其内部定义的变量!再回来看d,d只是在f内部定义了,而外部并没有权限访问它,所以这次报错d is not defined...
/*注意区分undefined 和 d is not defined,一个未赋值,一个根本未声明过。*/
作用域链
看上面栗子中的5,7,8行,分别用到了a和b两个变量,这两个变量在f中声明了么?并没有,那为什么还能输出正确的值呢?作用域链就在这时候登场了。f中找不到相应的变量时,向上(外部)一层一层寻找直到最外层,找到则引用,找不到则报错 -- 就是这么简单!
思考题
var a = 10;
var b = 5;
function f(){
console.log(a);
var a = 20;
console.log(a);
var d = 30;
var ff = function(){a++; b++; d++; console.log(a); console.log(b); console.log(d);}
return ff;
} var c = f();
c();
f()();
c();
好好想想这个思考题,注意return的部分,三思而后F12哦~~~
本文完。
我所理解的javascript中函数的作用域和作用域链的更多相关文章
- Javascript中函数的四种调用方式
一.Javascript中函数的几个基本知识点: 1.函数的名字只是一个指向函数的指针,所以即使在不同的执行环境,即不同对象调用这个函数,这个函数指向的仍然是同一个函数. 2.函数中有两个特殊的内部属 ...
- javascript中不存在块级作用域,所以要小心使用在块级作用域中的函数声明所带来的作用域混乱.
在javascript中函数的作用域是一个非常重要的概念. javascript中是没有块级作用域,但是有函数作用域的概念. 我们在开发的过程中,经常会遇到这样的问题, 某个函数我暂时不需要,不想声明 ...
- JavaScript 中函数节流和函数去抖的讲解
JavaScript 中函数节流和函数去抖的讲解 我们都知道频繁触发执行一段js逻辑代码对性能会有很大的影响,尤其是在做一些效果实现方面,或者逻辑中需要进行后端请求,更是会导致卡顿,效果失效等结果,所 ...
- JavaScript中函数是不能重载原因
以前有一次写JS插件的时候,由于后台写习惯了,妄想在JS中写重载函数,可惜不能成功,原因花了一点时间记了下来 首先要理解重载的含义:函数返回值不同或者形式参数个数不同但函数名相同的函数 JavasSc ...
- JavaScript中函数作为另一个函数的参数的时候它存在于哪个作用域
一直对函数作为参数被传递进另外一个函数理解的不是很清除.先看下这段代码吧: function test(fn){ var bar = 1; fn(); } var bar = 99; test(fun ...
- JavaScript中函数函数的定义与变量的声明<基础知识一>
1.JavaScript中函数的三种构造方式 a.function createFun(){ } b.var createFun=function (){ } c.var createFun=new ...
- JavaScript中函数的形参和实参的实现原理剖析
我们都知道JS里面参数的传递是可以不一样的,比如我们有一个函数: <script type="text/javascript"> function one(a,b,c) ...
- JavaScript中函数的调用
JavaScript中函数的调用 制作人:全心全意 在JavaScript中,函数定义后并不会自动执行,要执行一个函数需要在特定的位置调用该函数,调用函数需要创建调用语句,调用语句包含函数名称和参数. ...
- JavaScript中函数的定义
JavaScript中函数的定义 制作人:全心全意 在JavaScript中,函数是由关键字function.函数名加一组参数以及置于大括号中需要执行的一段代码定义的.定义函数的基本语法格式如下: f ...
随机推荐
- Android之RecyclerView轻松实现下拉刷新和加载更多
今天研究了下RecyclerView的滑动事件,特别是下拉刷新和加载更多事件,在现在几乎所有的APP显示数据列表时都用到了.自定义RecyclerView下拉刷新和加载更多听上去很复杂,实际上并不难, ...
- 2732: [HNOI2012]射箭( 半平面交 )
很久没写题解了= =,来水一发吧= = 首先这道题很明显就是求y=ax^2+bx的是否有值取,每一个式子都代表着两个半平面,然后直接半平面交就行了 借鉴了hzwer的代码,还是特别简洁的说 CODE: ...
- 解析java泛型(二)
上篇我们简单的介绍了java中泛型的最基本的内容,知道了什么是泛型以及泛型对我们的程序编写有什么好处,最后一类型限定收尾.本篇将从类型限定开始阐述java泛型中很重要的概念:通配符 一.何为通配符 ...
- CLOSE_WAIT TIME_WAIT
TCP状态转移要点 TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放.网络服务器程序要同时 ...
- collectionView布局
关于 collectionView的layout布局方法: 设置cell的间距,行间距,组与组之间的间距,都是在layout里面来设置. 包括,滚动方向. -(void)prepareLayout [ ...
- 读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用
一个关于赋值的有趣的事情是你可以将它们链在一起: int x, y, z; x = y = z = ; // chain of assignments 同样有趣的是赋值采用右结合律,所以上面的赋值链被 ...
- querySelectorAll与getElementsBy对比有什么不同
querySelectorAll与getElementsBy对比有什么不同javascript中的querySelectorAll与getElementsBy都可以获取dom元素对象,但是他们又有什么 ...
- Jsp,Servlet初学总结
一.Jsp 1. 指令: <%@page language="java" import="java.*" contextType="text/h ...
- Hibernate二级缓存原理
缓存:缓存是什么,解决什么问题? 位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为缓存Cache.缓存目的:让数据更接近于应用程序,协调速度不匹配,使访问速度更快 ...
- 基于Spring-WS的Restful API的集成测试
在很多Java企业级应用中,Spring占据了非常重要的位置,这就导致了基本上的技术选型都是围绕着Spring来, 比方说笔者最近的项目需要开发一个Restful的API接口,选型的时候就说,客户架构 ...