前言:本文属于学习笔记性质,让我们一起学习js。觉得有不对的地方,可以给我留言。 学习资料原型出处,感谢原作者的贡献
一、作用域链:
变量的作用域无非就是两种:全局变量和局部变量。下面我们来看一个例子:(注意var的使用)
var winVar = 1;
function outer(){
var outerVar = 2;
function inner(){
var innerVar = 4;
//var winVar = 10;
console.log(winVar);
}
inner(); //调用inner函数
}
outer(); //调用outer函数
函数内部声明变量的时候,注意var命令。如果不用的话,你实际上声明了一个全局变量!
JS首先在inner函数中查找是否定义变量winVar,定义了则使用inner函数中的winVar变量,如果inner函数中没定义winVar变量,js会继续在外层函数outer函数中查找是否定义了winVar变量,此处并没有,JS会继续向外层(全局对象)中查找是否定义了winVar,我在全局对象中定义了winVar=1,因此输出结果为1。
作用域链:JavaScript需要查询一个变量x时,首先会查找作用域链的第一个对象,如果以第一个对象没有定义x变量,JavaScript会继续查找有没有定义x变量,如果第二个对象没有定义则会继续查找,以此类推。
上述代码中涉及三个作用域对象:inner、outer、window。
二、函数体内部,局部变量的优先级比同名的全局变量高:
var a= 1; //定义全局变量 a
function check(){
var a = 100; //定义局部变量a
console.log(a); //这里会输出 100
}
check();
console.log(a); //这里会输出1
三、Js没有块级作用域:
下面代码中,变量i,j,k的作用域是相同的,他们在整个test函数体中是全局的
function test(){
// test函数体内存在三个局部变量 i j k
var i = 0;
if ( 1 ) {
var j = 0;
for(var k = 0; k < 3; k++) {
console.log(k) //分别弹出 0 1 2
}
console.log(k); //弹出3
}
console.log(j); //弹出0
}
输出结果
0
1
2
3
0
四、函数中声明的变量在整个函数中都有定义:
function test(){
var x=1;
function innerTest(){
x=100;
}
innerTest();
console.log(x);
}
test();
结果:
100
上面得代码说明了,变量x在整个test函数体内都可以使用,并可以重新赋值。
我们再来看如下的代码:
var x=1;
function test(){
console.log(x); //输出'undefined,没有输出1'
var x='hell world';
console.log(x); //输出'hello world'
}
test();
结果:
undefined
hello world
我们稍微做改动:
var x = 1;
function test1() {
console.log(x); //输出1'
}
test1();
结果:
1
解释:(针对第一种情况来说)在函数test内部,局部变量x在整个函数体内都有定义(var x=’hello world’,进行了声明),所以在整个test函数体内隐藏了同名的全局变量x。之所以弹出’undefined’是因为执行console.log(x)的时候,局部变量x还没有被初始化。
因此我们的test函数,等同于:
function test(){
var x;
console.log(x);
x = 'hello world';
console.log(x);
}
五、未使用var关键字定义的变量都是全局变量:
function test(){
x=100;
}
test();
console.log(x);
结果:
100
我们稍做修改:
function test() {
var x = 100;
}
test();
console.log(x); //结果Uncaught ReferenceError: x is not defined。它是个局部变量
六、全局变量都是window对象的属性:
var x=100;
console.log(window.x);
console.log(x);
结果:
100
100
等同于:
window.x=100;
console.log(window.x);
console.log(x);
结果:
100
100