我所理解的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 ...
随机推荐
- ASP.NET MVC用存储过程批量添加修改数据
用Entity Framework 进行数据库交互,在代码里直接用lamda表达式和linq对数据库操作,中间为程序员省去了数据库访问的代码时间,程序员直接可以专注业务逻辑层的编写.但是对于比较复杂的 ...
- 快速排序的C语言实现
#include <stdio.h> int qSort(int a[],int i,int j) { int h = i; int r = j; int x = a[h]; int f ...
- 对象this的引用
this关键字的最大作用就是让类中一个方法,访问该类里的另一个方法或者实例变量. public class Dog {//定义一个方法 public void jump() { System.out. ...
- .NET Core跨平台:使用.NET Core开发一个初心源商城总括
1..NET Core基本介绍 a 作为一个.NET的开发者,在以前的开发中,我们开发的项目基本都是部署在windows服务器上,但是在windows服务器上的话某些比较流行的解决访问量的方案基本都是 ...
- [翻译]现代java开发指南 第二部分
现代java开发指南 第二部分 第二部分:部署.监控 & 管理,性能分析和基准测试 第一部分,第二部分 =================== 欢迎来到现代 Java 开发指南第二部分.在第一 ...
- Dijkstra算法的二叉堆优化
Dijkstra算法的二叉堆优化 算法原理 每次扩展一个距离最小的点,再更新与其相邻的点的距离. 如何寻找距离最小的点 普通的Dijkstra算法的思路是直接For i: 1 to n 优化方案是建一 ...
- Javascript正则表达式(上)
正则表达式一般用于验证客户端的用户输入,而服务器端的PHP.ASP.NET等脚本无须再进行验证,节约了后台开销. 1.两种创建方法 var box=new RegExp("Box" ...
- fastcgi的介绍,原理及配置
fastcgi介绍: CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序一般运行在网络服务器上. C ...
- PHP+Jquery+Ajax 实现动态生成GUID、加载GUID
GUID: 全局唯一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度为128位的数字标识符.GUID主要用于在拥有多个节点.多台计算机的网络或系统中 ...
- 云服务器spark集群搭建
---恢复内容开始--- 1:去官网下载spark http://spark.apache.org 2:解压,然后在自己的机器上编译conf中的两个文件 mv slaves.template slav ...