码迷,mamicode.com
首页 > 其他好文 > 详细

一、关于作用域 作用域链的理解

时间:2015-02-11 10:40:58      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

作用域:每个函数有自己执行环境(个人理解即作用域),而其执行环境决定了那个环境中的变量和函数可以访问的数据的权限。

作用域链:从当前执行环境往外部检索(当前环境为此作用域链的最前端,全局环境为作用域链尾部),第一种情况检索成功,直到检索到对应变量为止;第二种情况检索失败,即找到全局环境还未找到相对应的变量,返回not defined的错误。

例:
function scopetest1() {

          var test1 = 1;            //可访问test1

 

          function scopetest2() {

            var test2 = 2;       //可访问test1以及test2

      

            function scopetest3() {

              var test3 = 3;        //可访问test1 test2以及test3

              test2 = test3;

              console.log(test2);   //3

              console.log(test3);   //3

            }

            scopetest3();

            test3 = 5;

              console.log(test3);     //5

            }

            scopetest2();

          }

 

          scopetest1();

对应的作用域范围

技术分享

Scopetest3作用域链:scopetest3—> scopetest2—> scopetest1—> window

具体检索过程:对于直接定义在当前环境的test3,在当前环境检索到之后便不再继续检索,对于定义在scopetest2的test2,现在scopetest3中检索是否定义test2,没有找到,往外部查找,即在scopetest2中查找,找到后匹配正确,检索结束。

Scopetest2作用域链:scopetest2—> scopetest1—> window

具体检索过程:对于test2直接检索到,对于test3,由于scopetest1以及全局环境中都没有,所以检索失败,返回not defined。

Scopetest1作用域链:scopetest1—> window

具体检索过程:对于test1直接检索到,检索结束。

 

注意:

1、声明一个变量时省略了var 关键字的时候,由于浏览器解析时的容错机制,会将此变量加入全局环境(严格模式下会报错)。

将上边代码做稍微的改动:

           function scopetest2() {

            var test2 = 2;          //可访问test1以及test2

              function scopetest3() {

               //省略

              }

            scopetest3();

            test3 = 5;

              console.log(test3);     //5

            }

            scopetest2();         

这个时候控制台输出并没有报错,而是在初始化的时候把test3加入了全局环境,这个时候全局环境和scopetest3中都有了test3变量,其效果相当于:

var test3;  

function scopetest1() {

          var test1 = 1;            //可访问test1

 

          function scopetest2() {

            var test2 = 2;       //可访问test1以及test2

            function scopetest3() {

            //省略

            }

            scopetest3();

            test3 = 5;

              console.log(test3);     //5

            }

            scopetest2();

          }

          scopetest1();

此时scopetest3中定义的test3的值依然是3。

 2、当分别在不同环境中声明同名变量时,离当前环境最近的变量将会覆盖其他环境定义的变量,如下:

function scopetest1() {

  var test1 = 1;

  var test2 = 2;        

 

  function scopetest2() {

    var test1;

    var test2 = 3; 

    console.log(test1+" "+test2);  //undefined 3 

  }

  scopetest2();

  console.log(test1+" "+test2);     //1 2

}

scopetest1();

这里scopetest2里test1只进行了声明而没有进行初始化,但是依旧覆盖了scopetest1中进行初始化的test1。

3、无块级作用域

之前常常会把块级作用域与函数的执行环境弄混淆,在这里区别一下。

 

function mytest2 (){

  var i;

  for(i=0;i<10;i++){

    var j = i;

  }

  console.log("结束循环"+j);    //控制台输出9

 

}

mytest2();

 

在for中定义的变量j在花括号之外依旧存在,其变量是加入到最近的环境中的,在js中if while等都没有块级作用域,自己定义的函数都具有自己的执行环境,即作用域。可以通过匿名函数来模仿块级作用域。

一、关于作用域 作用域链的理解

标签:

原文地址:http://www.cnblogs.com/wangpq/p/4285382.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!