码迷,mamicode.com
首页 > Web开发 > 详细

js闭包和作用域链

时间:2015-09-10 08:24:51      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

闭包

闭包

函数对象之间可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内

这种特性称做“闭包”。

 

什么是变量?

变量就是为一切事物赋的一个name;

var的作用,初始化变量。

变量作用域

程序源码中定义这个变量的区域就就是变量作用域。(名字放在什么地方了)

全局变量拥有全局作用域,在js代码的任何地方都是有定义的。(这个名字很响亮)

在函数体内声明的变量在函数体内有效,他们是局部变量,函数参数也是局部变量他们只在函数体内有定义。(里层的能拿到的外层的值,外层的拿不到里层的值)

在函数体内,同名的局部变量优先级要高于同名的全局变量,函数参数也是一个局部变量。

 实例1 var scopte = “gloabl”;

function checkscope(){

var scope = “local”;

return scope;

}

checkscope() //  “local”;

 

 实例2var attri = 100;  //全局变量与函数参数同名,全局变量被遮盖。
    function fuck( attri ){
        alert(attri);
    }
fuck(10); //10

 

 实例3

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function nested(){
        var scope = "nested scope";
        return scope;
    }
    return nested();
}
checkscope(); // “nested”;

 

js中没有块级作用域,取而代之的是函数作用域。

变量在声明的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

声明提前 (遇到var的地方就会声明提前)

实例4

function test(o){

/*i在整个函数体内均是由定义的*/
    var i = 0;                            
    if( typeof o=="object"){

/*j 在函数体内是用定义的,不仅仅是在这个代码段*/
        var j=0;  

 /*k在函数体内是有定义的,不仅仅是在循环内*/                        

        for( var k=0; k<10;k++){       
            console.log(k);                //输出0~9
        }
        console.log(k);                    //10
    }
    console.log(j);                        //j已经定义了,但可能没有初始化。
}

等价于

function test(o){
    var i;
    var j;
    var k;
    i = 0;                            
    if( typeof o=="object"){
        j=0;                       
        for( k=0; k<10;k++){        
            console.log(k);           
        }
        console.log(k);              
    }
    console.log(j);  

实例5

var scope = "global";
 function f(){
     console.log(scope);         //调用f()输出undefined声明提前
     var scope = "local";         //虽然不是第一行代码,但是实际scope已经声明了。
     console.log(scope)          //调用f()输出local
 }

等价于

var scope = “global”;

function f(){

var scope ;  

console.log(scope);

scope = “local”;

console.log(scope);js中没有块级作用域,取而代之的是函数作用域。

}

 

作用域链( 作用域链是特殊的对象列表object-List 

定义函数的是很创建作用域对象,创建的作用域对象组成作用域链。

谈论作用域的时候要声明是哪段代码。就像我们某人的时候要说明是哪一个人。0

每一段JavaScript代码都有一个与之关联的作用域链,(js中没有块级作用域,取而代之的是函数作用域。)这个作用域链是一个对象列表。对象列表中定义了这段代码作用域中的对象。

 

var 创建的变量时不可配置的,不可通过delete操作符删除。

全局变量在程序中始终是有定义的,局部变量在声明的函数体内以及所嵌套的函数体内始终是由定义的。

 

如果将局部变量看做自定义对象的属性的话,可以换个角度来解读变量作用域,每一段js代码都有一个与之关联的作用域链,作用域链是一个对象列表(object-List,object-List定义了这段码作用域中的变量。当js需要变量x的时候(这个时候称作变量解析),它会从object-List中第一个对象开始查找,如果用这个变量x就直接使用,没有查找下一个object-List中的下一个对象,如果查询了所有的object-List对象中都没有x这个变量,则抛出一个引用错误。

 

作用域链类型

   (1js的最顶层代码中(不包含任何函数定义内的代码),保存的作用域链由1个全局对象组成。

 

(2)在定义不包含嵌套的函数体内,保存的作用域链由2个对象组成,第1个对象是定义函数参数和局部变量组成的,第2个是全局对象。

 

(3)在定义一个嵌套的函数体内,保存的作用域链上至少包含3个对象,第1个是嵌套函数内的参数和局部变量组成的对象,第2个对象是外层函数的参数和局部变量组成的,第3个对象是全局对象。

 

作用域链的创建规则

   当定义一个function时,这个function实际上保存了一个作用域链object-List,当调用这个function时,这个function创建一个新的object类似于通过构造函数创建对象)来保存它自己的局部变量,然后将这个创建的object添加到保存的那个作用域链object-List上,原来的object-List就增加了一个对象,

function a(){ var c ; } //创建这个函数的时候保存了一个object-List

a() //调用这个函数的时候创建了一个新的object来保存自己的局部变量,并将这个对象添加到作用域链object-List中,使定义该函数时的作用域链变长,然后创建一个新的更长的表示函数调用作用域的“链”。

实例7

var i =0;

/*定义这个function的时候有2个作用域链 object-1为空,object-2 var i这个变量值。*/
     function a(){ 

         i++;
         alert(i);
     }

/*调用这个函数的时候会创建一个变量对象改变定义function时候的作用域链,object-1为空,object-2var i 发生改变*/
    a();    //1
    a(); //2

 

 

对于嵌套函数来讲,每次调用外部函数,都会使定义该外部函数时的作用域链变长,所以内部嵌套函数每次的作用域链也会微妙的不同。嵌套的里层函数作用域构成包含了外层函数的作用域链,外层函数的作用域发生改变,里层函数的作用域链也会开始改变。

                   

 

调用函数是什么意义?

js闭包和作用域链

标签:

原文地址:http://www.cnblogs.com/yuanxiaofeng/p/4796691.html

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