载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25076713

一直觉得Js很强大,由于长期不写js代码,最近刚好温故温故。

1、Javascript没有代码块作用域的概念,局部作用域是针对函数来说的。

  1. function fun()
  2. {
  3. for( var i = 0 ; i < 10 ; i++)
  4. {}
  5. //如果在Java中i此时应当属于未声明的变量,但是Js中i的作用域依然存在
  6. console.log(i);//10
  7. if(true)
  8. {
  9. var b = "helloworld";
  10. }
  11. console.log(b);//helloworld
  12. }
  13. fun();

2、如果不使用var声明的变量,默认为全局变量

  1. function fun02()
  2. {
  3. a = "helloworld";
  4. var b = "welcome";
  5. }
  6. fun02();
  7. console.log(a); //     helloworld
  8. console.log(b); //   b is not defined

3、Js中的作用域链

先看个简单的例子:只有一个函数对象,函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。

  1. var a = "hello";
  2. function fun04()
  3. {
  4. a = "world";
  5. var b ="welcome";
  6. }

作用域链的图:


注:图中省略了,Global Scope中的window,document等,每个函数对象中的arguments,this等均未画出。

  1. function fun03()
  2. {
  3. var a = 10;
  4. return function(){
  5. a*= 2 ;
  6. return a ;
  7. };
  8. }
  9. var f = fun03();
  10. f();
  11. var x = f();
  12. console.log(x);  //40
  13. var g = fun03();
  14. var y = g();
  15. console.log(y); //20

观察上面代码,存在fun03,f,g三个函数对象。

下面是作用域链的图:

注:每个函数对象一个作用域链,这里直接画在了一起;对于变量的查找,先从链的0开始找。

函数对象 f 在代码中执行了2 次,所以a*2*2 = 40 ; 函数对象 g 在代码中执行了1次, 所以 a *2 = 20 ;

4、闭包

上面的例子可以看到,在fun03执行完成后,a的实例并没有被销毁,这就是闭包。个人对闭包的理解是:函数执行完成后,函数中的变量没有被销毁,被它返回的子函数所引用。

下面以一个特别经典的例子,同时使用作用域链解析:

  1. window.onload = function()
  2. {
  3. var elements = document.getElementsByTagName("li");
  4. for(var i = 0; i < elements.length ; i ++)
  5. {
  6. elements[i].onclick = function()
  7. {
  8. alert(i);
  9. }
  10. }
  11. }

相信上面的代码肯定大家都写过,本意是点击每个li,打印出它们的索引,可是事实上打印出的都是elements.length。这是为什么呢?

看下上面的简易的作用域链(省略了很多部分,主要是理解),此时每个onclick函数的i,指向的都是 onload 中的i 此时的 i = element.length.

下面看解决方案:

  1. window.onload = function ()
  2. {
  3. var elements = document.getElementsByTagName("li");
  4. for (var i = 0; i < elements.length; i++)
  5. {
  6. (function (n)
  7. {
  8. elements[n].onclick = function ()
  9. {
  10. alert(n);
  11. }
  12. })(i);
  13. }
  14. }

在onclick函数的外层,包了一层立即执行的函数,所以此时的n指向的 n 是立即执行的,所有都是1~elements.length 。

----------------------------------------

以上原子 摘抄的  (文章开头的链接)

----------------------------------------

其实,关于上面循环中,i获取到的始终是  elements.length的问题,只需要 将 i 的值定义一个变量 存放一下,也可以解决。

(转载)Javascript 进阶 作用域 作用域链的更多相关文章

  1. JavaScript进阶之原型链

    对象 function f1(){ }; typeof f1 //"function"函数对象 var o1 = new f1(); typeof o1 //"objec ...

  2. JavaScript面向对象的作用域链(转载)

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...

  3. 深入理解 JavaScript 变量的作用域和作用域链

    一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...

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

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

  5. javascript笔记:javascript的关键所在---作用域链

    javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...

  6. 深入理解JavaScript的变量作用域(转载Rain Man之作)

    在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...

  7. javascript的关键所在---作用域链

    javascript的关键所在---作用域链 javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript ...

  8. 认识Javascript中的作用域和作用域链

    作用域 只要写过java或者c#等语言的同学来说,相信一定能理解作用域的概念,在作用域的范围中,我们可以使用这个作用域的变量,对这个变量进行各种操作.可是,当使用Javascript的时候,相信很多的 ...

  9. JavaScript之作用域-作用域链

    作用域 ==> 作用域链   作用域:变量可以其作用的区域(声明定义好一个变量,变量可以在哪些范围内使用) 分类:全局作用域和局部作用域(函数作用域):在js中,目前全局有作用域以及函数可以形成 ...

  10. Javascript之变量作用域

    分析: 无论是强类型语言c#.c++.java等语言,还是弱类型语言如Javascript,所有变量可以抽象为两种类型,即局部变量和全局变量. 全局变量:整个作用域可见. 局部变量:局部可见,退出作用 ...

随机推荐

  1. Java语言基础(四) String和StringBuffer的区别

    Java提供了两个字符串类:String和StringBuffer. String提供了数值不可变的字符串,而StringBuffer提供的字符串对象可以进行修改. 当知道字符数据要改变的时候就可以使 ...

  2. Android ServiceConnection类的onServiceDisconnected(ComponentName name)在什么时候执行

    ServiceConnection类中的两个方法非别在服务连接成功时.不成功时调用.其中onServiceDisconnected()方法在连接正常关闭的情况下是不会被调用的, 该方法只在Servic ...

  3. 读懂Java中的Socket编程

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...

  4. Windows Azure功能更新:SQL Server AlwaysOn和Notification Hub 正式商用

    一周以前Windows Azure发布了新的更新内容,主要的更新有3项: 虚拟机上的SQL Server支持AlwaysOn可用性组了 Notification Hub商用 自动缩放支持时间策略 这里 ...

  5. BZOJ1232: [Usaco2008Nov]安慰奶牛cheer

    1232: [Usaco2008Nov]安慰奶牛cheer Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 578  Solved: 403[Submi ...

  6. leetcode distinct-subsequences(DP)

    参考https://oj.leetcode.com/problems/distinct-subsequences 动态规划方程 dp[i][j]=dp[i-1][j-1]+dp[i-1][j] (s( ...

  7. 公有云开启全面竞争时代——青云QingCloud

    网界网本期[封面报道]公有云开启全面竞争时代 [CNW.com.cn 专稿] 险滩急流之后,公有云[注]服务市场的开拓者们终于看到了一片丰饶之海. 2013年,中国云计算[注]产业起步的第五年,公有云 ...

  8. Java编程-第一个Java程序

    Java编程用到的IDE是Eclipse. 关于第一个Java程序实现的简单流程: (1)    下载eclipse (2)    File-New-Java Project 命名工程名字:Hello ...

  9. 创建maven项目出现的问题

    右击项目无法显示maven图标,创建的pom.xml无法识别,并且创建maven项目时,一直显示Loading archetype list...

  10. MyBatis完全使用指南

    MyBatis完全使用指南 转 http://www.jianshu.com/p/1c7c7d1bba33 MyBatis MyBatis作为一个轻量的SQL映射框架,确实很简单,但是知识点挺多,实际 ...