对JavaScript作用域的认识(一)

1、首先是作用域的一个概念 :简单地将作用域分为两部分 :

1)作用  作用即程序的读与写(虽然并不完整 但暂时这样理解)

2)域       域就是空间 范围 区域

那么在JS中最最常见的两个作用域就是<script></script>和 function(){} 这两者的区别可以看成是  :

1)<script></script>是一个全局的函数  由上到下进行解析(当有很多个<script>作用域时)

2)function(){} 由里向外

2、其次需要有一个浏览器解析的步骤认识(作用域都是先解析后执行的)   浏览器对JS代码的解析是从<script>标签开始的   分为两步:

1)JS预解析(可以看成是一个“仓库”  把解析出来的东西先放进这个“仓库”内)  解析的东西包括:

①var 变量   JS中因为没有明确定义变量时要具体定义成什么变量  所以在浏览器预解析到有变量的时候 先把变量名放入"仓库"

 而不去管这个变量是什么类型的变量 全部赋以undefined值

②function函数     在正式运行代码之前  将整个函数块先放入“仓库‘中

③参数  性质和变量一致

那么这里又会出现一个新的问题  预解析的时候如果遇到重名问题  最常见的概括为以下两种情况:

①变量与函数重名时   留下函数(这与函数和变量在代码中出现的先后次序是无关的)这是因为此时的变量是个undefined值

而函数function也是一个类型  比起undefined更具有意义

②函数与函数或者是变量与变量重名时  就遵循后面的覆盖掉前面的函数或变量(先后次序原则)

2)逐行解读代码  在预解析后开始逐行解释代码   这边表达式就可以修改预解析的值(也就是修改"仓库"中的值)

具体表达式 可以是 = +  -   *  /  %  ++    --   !    ||  &&   参数等等等..........

3、作用域链

如果预解析时子级没有找到相应的声明  会往父级找  直到找到最顶级的作用域  此时子级中对父级变量的表达式影响的就是父级的变量
 具体看例子4)

但是反过来父级却不会向子级中去找子级预解析时没有解析到的变量  所以想让父级能够得到子级中的变量的值
 具体可以看下述内容“其他”

当然作用域链中经常使用到的是with语句 用来临时改变当前作用域

具体例子分析:

1)"仓库"中的重命名问题

   <script>
        /*重名问题的分析 第一步预解析 发现有变量与函数重名问题那么保留函数
        也有函数与函数重名问题 保留"后出现"的函数 即最后仓库中保留的是函数块function a(){alert(4);}
        下面进行逐步解析*/
        alert(a);   // 发现仓库中有函数块a  所以输出function a(){alert(4);}
        var a = 1;  //发现是个表达式  修改仓库中a的值 由函数块改为变量a = 1;
        alert(a);   //发现仓库中有a = 1 输出1
        function a() {  //逐行解析时函数只是一个声明  只有表达式才可以改变"仓库"中变量值
            alert(2);
        }
        alert(a);  //输出1
        var a = 3;  // 仓库中a的值改为3
        alert(a);   //输出3
        function a() {   //同理
            alert(4);
        }
        alert(a);  //输出3
        a();  //此时a是一个值 而不是函数  所以报错a is not a function
    </script>

2)作用域问题1  输出结果为 undefined    1

    <script>
        /*现在函数fn1是<script>的子级,先进行预解析(注意此时的预解析只是针对全局<script>的)
          预解析的结果是 a = undefined  function fn1(){alert(a); var a = 2;}*/
        var a = 1;     //全局预解析中的a变量变为1
        function fn1() {
            alert(a);   //由下述预解析的结果可以知道输出undefined
            var a = 2;  //函数作用域中的a变量变为2,函数执行结束后由GC回收
        }
        fn1();   // 调用函数,进入函数的作用域,先进行预解析,预解析的结果是a = undefined
        alert(a);  //输出全局预解析中的a 即现在的1
    </script>

3)作用域问题2   输出结果为1   2   1

    <script>
        /*<script>作用域预解析后结果为 a = undefined function fn1(a){...}*/
        var a = 1;
        function fn1(a) {  //此时a是一个参数 参数也是表达式 此时相当于是var a = 1;
            alert(a);  //输出1
            var a = 2;   //表达式改变a的值 a = 2
            alert(a);  //输出2,函数结束GC回收
        }
        fn1(a); /*函数fn1的预解析结果为 a = undefined*/
        alert(a);  //输出<script>域中的a = 1;
    </script>

3)* 多了一个arguments的使用  其实在function中参数a 变量a和arguments[0]是一样的

    <script>
        /*预解析为 a = undefined function fn1(a){...}*/
        var a = 1;  // a = 1;
        function fn1(a) {   // 相当于var a = 1;
            arguments[0] = 3;  //相当于 a = 3;
            alert(a);  //output number 3
            var a = 2;  // a = 2;
            alert(arguments[0]);  //output number 2
        }
        fn1(a);  /*预解析为 a = undefined*/
        alert(a); //output number 1
    </script>

4)作用域链问题

    <script>
        /*<script>作用域的预解析结果为a = undefined   function fn1(){...}*/
        var a = 1;  //改变a的值为a = 1
        function fn1() {
            alert(a);  //在自己的预解析"仓库"中没有找到a 那么就往父级<script>作用域的预解析"仓库"中找,结果
                        //找到了a = 1那么就输出
            a = 2;  //改变父级<script>作用域中a的值 a = 2 注意现在fn1的"仓库"是空的 所以GC没有东西可以回收;
        }
        fn1();  /*预解析时候碰到没有var的变量声明  也没有函数声明  可以看成现在的函数的仓库为空*/
        alert(a);  //输出 a = 2;
    </script>

其他:所以由上一些内容可以知道如果想要获取函数内的值基本上就可以通过两种方式

1)利用作用域链  让父级的变量去获取

    <script>
        var str;
        function fn1() {
            var tmp = ‘abc‘;
            str = tmp;
        }
        fn1();
        alert(str);
    </script>

2)

    <script>
        function fn1() {
            var tmp = ‘abc‘;
            fn2(tmp);
        }
        function fn2(a) {
            alert(a);
        }
        fn1();
    </script>
时间: 2024-10-10 11:11:18

对JavaScript作用域的认识(一)的相关文章

JavaScript作用域链

JavaScript作用域链 之前写过一篇JavaScript 闭包究竟是什么的文章理解闭包,觉得写得很清晰,可以简单理解闭包产生原因,但看评论都在说了解了作用域链和活动对象才能真正理解闭包,起初不以为然,后来在跟公司同事交流的时候发现作用域和执行环境确实很重要,又很基础,对理解JavaScript闭包很有帮助,所以在写一篇对作用域和执行环境的理解. 作用域 作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域. 单纯

深入理解javascript作用域系列第四篇——块作用域

× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的代码,比如块作用域.随着ES6的推广,块作用域也将用得越来越广泛.本文是深入理解javascript作用域系列第四篇——块作用域 let for (var i= 0; i<10; i++) { console.log(i); } 上面这段是很熟

深入理解javascript作用域系列第一篇——内部原理

× 目录 [1]编译 [2]执行 [3]查询[4]嵌套[5]异常[6]原理 前面的话 javascript拥有一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量,这套规则被称为作用域.作用域貌似简单,实则复杂,由于作用域与this机制非常容易混淆,使得理解作用域的原理更为重要.本文是深入理解javascript作用域系列的第一篇——内部原理 内部原理分成编译.执行.查询.嵌套和异常五个部分进行介绍,最后以一个实例过程对原理进行完整说明 编译 以var a = 2;为例,说明javasc

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. JavaScript作用域 任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 1.  全局作用域(Global S

JavaScript作用域和作用域链

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链 来源:梦想天空  http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html 作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. Java

五个小例子教你搞懂 JavaScript 作用域问题

众所周知,JavaScript 的作用域和其他传统语言(类C)差别比较大,掌握并熟练运用JavaScript 的作用域知识,不仅有利于我们阅读理解别人的代码,也有助于我们编写自己的可靠代码. 下面笔者将使用五个小例子来给大家分析下 JavaScript 的作用域要注意的问题. 感谢 例子的来源 (这5个例子我做错了2个 [嘿嘿,尽情鄙视吧],笔者就是要 死磕自己,奉献大家!) 先给出五个例子: 每个例子旁边都会给出答案的链接,如果你全部都正确了,你可以忽略这篇短文,并深深的鄙视下笔者. 例一:

Python自动化 【第十六篇】:JavaScript作用域和Dom收尾

本节内容: javascript作用域 DOM收尾 JavaScript作用域 JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.JavaScript中无块级作用域 在Java或C#中存在块级作用域,即:大括号也是一个作用域. 1 public static void main () 2 { 3 if(1==1){ 4 String name = "seven"; 5 } 6 System.o

关于Javascript作用域及作用域链的总结

本文是根据以下文章以及<Javascript高级程序设计(第三版)>第四章相关内容总结的. 1.Javascript作用域原理,地址:http://www.laruence.com/2009/05/28/863.html 2.JavaScript 开发进阶:理解 JavaScript 作用域和作用域链,地址:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html 在介绍有关作用域的内容之前,先来介绍

Javascript作用域和变量提升

下面的程序是什么结果? [javascript] view plain copy var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 结果是10: 那么下面这个呢? [javascript] view plain copy var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a); 结果是1. 吓你一跳

理解javascript作用域和作用域链

作用域 作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域. 全局和局部作用域下面用一张图来解释: 单纯的JavaScript作用域还是很好理解的. 作用域链 全局执行环境是最外层的一个执行环境,在web浏览器中全局执行环境是window对象,因此所有全局变量和函数都是作为window对象的属性和放大创建的.每个函数都有自己的执行环境,当执行流进入一个函数的时候,函数的环境会被推入一个函数栈中,而在函数执行完毕后执行