我们来看下面的几个小例子
1 首先来个最简单的:
var a = 1;
function test1(){
console.log(a);
}
test1(); //=>1
这个程序输出1肯定没什么问题了,函数局部作用域内没有局部变量a,因此沿着作用域链向上查找,找到了全局变量a,于是输出。
2 接下来添加个局部变量:
var a = 1;
function test1(){
var a = 2;
console.log(a);
}
test1(); //=>2
这段程序输出2,因为沿着作用域链向上查找时,首先找到的是局部变量a是2,于是将2输出.
3 继续变形
var a = 1;
function test1(){
console.log(a);
var a = 2;
console.log(a);
}
test1(); //=>undefined 2
这时第一个console.log(a)输出undefined,第二个输出2,第二个其实不难理解,但是有可能有人不能理解第一个为什么会输出undefined。其实主要是变量声明提升(javascript引擎在执行时,会把所有的变量的声明都提升到当前作用域的最前端)的问题,即上面的代码相当于
var a = 1;
function test1(){
var a;
console.log(a);
a = 2;
console.log(a);
}
test1();
这时,当第一次要输出a时,程序会首先在局部作用域中查找a,在这个函数中,程序找到了变量a,故不会继续沿着作用域链向上查找,但是这里的a只声明了并没有进行初始化,故默认为undefined。
4 接下来,看一下下面的代码会输出什么
var a = 1;
function test2(){
console.log(a);
}
function test1() {
var a = 2;
test2();
}
test1();
输出的是1 ,为什么呢,我们要清楚,在test1中,我们只是让test2函数执行了,而test2仍在全局环境中,并不是test1的局部环境,故test2根本不会访问到位于test1局部环境中的a。
5 对4中的代码进行修改,我们来看一下将test2定义在test1中的情况
var a = 1;
function test1() {
var a = 2;
function test2(){
console.log(a);
}
test2();
}
test1();
这样一来,test2在test1的局部环境中,a自然就会输出2。
6 接下来我们来看看对象中的方法
var a = 1;
var b = {
a: 2,
show:function(){
console.log(a);
}
}
b.show(); //=>1
单纯的这样看这段代码为什么会输出1可能会不太明显,但是如果稍微转换一下,就很好明白了。
var b = {
a: 2,
show:function(){
console.log(a);
}
}
其实是相当于
var b = {};
b.a = 2;
b.show = function(){
console.log(a);
}
这样很明显就看出a应该是全局环境中的a了.
7 与上面例子类似的,看下面的代码:
var a = 1;
var b = {
a: 2,
show:function(){
console.log(this.a);
}
}
b.show(); //=>2
上面是经常使用的,定义对象的方式,使用了this关键字,将a与当前的执行对象绑定,输出的是当前执行对象的a属性,故输出2.
8 再继续对上面的例子进行变形
var a = 1;
var b = {
a: 2,
show:function(){
console.log(this.a);
}
}
var c = b.show;
c(); //=> 1
这里是个比较容易出问题的地方,需要注意的是,this指向的是执行时的当前对象,在上个例子中,直接调用b.show(),show方法的执行环境是b,故输出的是b.a,但是在这个例子中,c指向的是function(){console.log(this.a)},相当于你在全局环境中定义c
var c = function(){
console.log(this.a);
}
这里c的执行环境是全局环境,故应输出window.a
注:本文无意误导大家,如有错误欢迎指出!