变量的声明
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.all是window对象下面的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”。
如果觉得此篇文章对您有帮助,希望可以请我喝雪碧!