JavaScript--变量作用域、函数作用域及作用域链

来源:互联网 发布:ug8.0编程实例教程pdf 编辑:程序博客网 时间:2024/05/29 13:02

JavaScript–变量作用域、函数作用域及作用域链

变量作用域

一个变量的作用域是代码中定义这个变量的区域。

  • 全局变量拥有全局作用域,在js代码中任何地方都有定义
  • 在函数内声明的变量只在函数体内有定义——局部变量,函数参数也是局部变量,只在函数体内有定义

在函数体内,局部变量的优先级高于同名的全局变量。

var scopr="global";//全局变量function checkscope(){    var scope="local";//同名局部变量    return scope;//返回局部变量值而不是全局变量}checkscope();//local

函数作用域

JS没有类似C语言的块级作用域,使用函数作用域:变量在声明他们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

function test(o){    var i=0;//i在整个函数体内有定义    if(typeof o=="object"){        var j=0;//j在函数体内是有定义的,不仅仅是这个代码段内        for(var k=0;k<10;k++){ //k在函数体内是有定义的,不仅仅是这个循环内            console.log(k);//输出0-9        }        console.log(k);//输出10    }    console.log(j);//j已经定义了,但可能没有初始化}

由于函数作用域的特点,js实现了声明提前:函数里声明的所有变量(但不涉及赋值),都提前至函数顶部。

如下例:

    var scope="global";    function f(){        console.log(scope);//输出undefined,而不是global        var scope="local";//变量在这里初始化赋值。但变量本身在函数体内任何地方都有定义        console.log(scope);//输出local    }

相当于:

    var scope="global";    function f(){        var scope;        console.log(scope);//输出undefined,而不是global        scope="local";//变量在这里初始化赋值。但变量本身在函数体内任何地方都有定义        console.log(scope);//输出local    }

声明函数和变量

  • 声明变量,变量不能删除(delete),属性可以删除

变量的声明只有一种方式,那就是用var关键字声明,直接赋值不是一种声明方式。这仅仅是在全局对象上创建了新的属性(而不是变量)。

var a=10;//变量b=10;//不是变量,是在全局对象上创建了新的属性(不会声明提前)alert(delete b); // truealert(window.b); // undefined

但是,在“eval”的上下文中,变量是可以删除的:

eval('var a = 10;');alert(window.a); // 10alert(delete a); // truealert(window.a); // undefined
  • 函数声明

函数的声明有三种方式

1function name( ){ }直接创建方式(2new Funtion构建函数创建(3)给变量赋值匿名函数方法创建function add(a,b){    return a+b;}var add=new Function("a", "b", "return a+b;");var add = function(a,b){    return a+b;}add(4,5);

当变量名和函数名声明时相同,函数优先声明。

作用域链

将局部变量看作是自定义实现的对象的属性

每一段JS代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)

这个作用域链是一个对象列表或者链表,这组对象定义了这段代码“作用域中”的变量。当JS查找变量X的值的时候,它从链中的第一个对象开始查找,如果这个对象有名为x的属性,则直接使用该属性值,否则JS继续查找下一个对象,直至找完不存在X,抛出引用错误一场(ReferenceError)

在JS的最顶层代码中,作用域链就是一个全局对象组成

function add(a,b){    var sum = a + b;    return sum;}此时作用域链(Scope Chain)只有一级,就为Global Objectscope(add) -> Global Object(VO)

当调用这个函数的时候,它创建了一个新的对象来存储它的局部变量,将这个对象添加至保存的那个作用域链上。

add(1,2);//此时作用域链就有2级了scope(add) -> activation object(AO)-> Global Object(VO)

嵌套的函数体内,作用域链至少有3个对象

function add(a,b){    var sum = a + b;    function add2() {        var z = 30;        console.log(a + b + z);    };    add2()}add(3,4);//此时scope -> add2.AO -> add.AO -> Global Object

此时这三个对象:

add2.AO = {        z : 30,        __parent__ : add.AO    }add.AO = {        this:window,        arguments : [3,4],        a : 3,        b : 4,        add2 : <reference to function>,        __parent__ : <Global Object>    }Global Object = {        this:window,        add: <reference to function>,        __parent__ : null    }
0 0