JavaScript学习:变量作用域

王叨叨 | 2014-07-01 | 分类 笔记  | 标签 js  reading_notes 

变量的声明

JS中变量申明分显式申明和隐式申明。

var i=100;//显式申明
i=100;//隐式申明

在函数中使用var关键字进行显式申明的变量是做为局部变量,而没有用var关键字,使用直接赋值方式声明的是全局变量。

在使用var关键字声明变量时,这个变量将被自动添加到距离最近的可用环境中。对于函数而言,这个最近的环境就是函数的局部环境;如果变量在未经声明的情况下被初始化,那么该变量会被自动添加到全局环境。

虽然省略var操作符可以定义全局变量,但这也不是我们推荐的做法。因为在局部作用域中定义的全局变量很难维护,而且如果有意地忽略了var操作符,也会由于相应变量不会马上就有定义而导致不必要的混乱。给未经声明的变量赋值在严格模式下会导致抛出ReferenceError错误。

全局变量和局部变量

当JS解析器执行时,首先就会在执行环境里构建一个全局对象,我们定义的全局属性就是做为该对象的属性读取,在顶层代码中我们使用this关键字和window对象都可以访问到它。而函数体中的局部变量只在函数执行时生成的调用对象中存在,函数执行完毕时局部变量即刻销毁。

变量作用域

执行环境有全局执行环境(也称为全局环境)和函数执行环境之分; 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链; 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境; 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;

代码分析+反思

1. 作用域分析

function t() { 
    var a; 
    function t2() { 
        var b; 
    } 
}

js中函数也是对象,所以变量a所在的对象是t,t又在window对象中,所以a的作用域链:t–window 那么b所以在的对象即t2,t2又包含在t中,t又在window对象,所以b的作用域链:t2–t–window

2. Javascript没有var的变量都为全局变量,且为window对象的属性

function test1() { 
    all = 30; 
    alert(all); 
} 
test1();
//30
alert(all); 
//30
alert(window.all);

如果把上面的代码修改一下:

function test1() { 
    var all = 30; 
    alert(all); 
} 
test1();
//ReferenceError: all is not defined
alert(all); 
//undefined,这里为啥会弹出undefined呢?
alert(window.all);

反思:这里我理解的意思是window.allwindow对象下面的all属性,系统 检测到window对象但是没有检测到all属性,所以 undefined!

3. 函数内部的变量取代全局同名变量

var t = "bb"; 
function test() { 
    //为什么弹出undefined?
    alert(t); 
    var t = "aa"; 
    //aa
    alert(t); 
}
test();
alert(t);

反思:由于函数作用域的特性,局部变量在整个函数体始终是有定义的,也即,在函数体内局部变量遮盖了同名全局变量,但是只有在程序执行到var语句的时候,局部变量才会被真正的赋值。因此,上述过程相当于,将函数内的变量声明提前至函数体顶部,同时变量初始化留在原来的位置。就相当于如下这个函数

var t = "bb"; 
function test() { 
    //将函数内的变量声明提前至函数顶部
    var t;
    alert(t); 
    var t = "aa"; 
    //aa
    alert(t); 
}
test();

再次修改下代码:

var t = "bb"; 
function test() { 
    //bb
    alert(t); 
    t = "aa"; 
    //aa
    alert(t); 
}
test();

反思:由于函数体内的t变量没有用var声明,就默认为全局变量,当然就不存在变量提前声明的问题。第一行就会输出”bb”,而第三行改变了t全局变量的值,输出了”aa”。

如果觉得此篇文章对您有帮助,希望可以请我喝雪碧!请我喝雪碧

上一篇   下一篇   返回顶部