作用域和声明前置的几道题

       今天下午看书的时候,群里有人问到这道题。挺有意思的。自己琢磨了一下,索性总结一下。以免以后在遇到这种类似的坑。

作用域和变量提升

关于作用域和变量提升,我博客之前总结过,这里就不再叙述。直接步入正题。

1
2
3
4
5
6
7
8
9
10
11
12
alert(a);                   
var a = 1;
alert(a);
function a (){ alert(2); }
alert(a);
var a = 3;
alert(a);
function a (){ alert(4); }
alert(a);

alert( typeof a );
a();

上面这个例子看起来很乱。但是我们动动手把他变回本来面目就很清晰了。

声明前置

1
2
3
4
5
6
7
8
9
10
11
var a;
function a(){alert(2);}
function a(){alert(4);}
alert(a);//{alert(4);}
a=1;
alert(a);//1
a=3;
alert(a);//3
alert(a);//3
alert(typeof a);//"number"
a();//报错。这里a已经是数字3,而非一个函数

我想现在 这简直就是一道送分题啊!,
对于声明前置我感觉最好的方法就是再从新写一次。把该声明的变量和函数都弄到前面去,(这里变量的优先级高于函数,变量在前,函数在后);


作用域

1
2
3
4
5
6
7
var a = 1;
function fn1(){
alert(a);
var a = 2;
}

fn1();

alert(a);

这道题考察的也是作用域链和声明前置。还是老方法
转换后:

1
2
3
4
5
6
7
8
var a;
function fn1(){
var a;
alert(a);//undefined;
a=2;
}

fn1();

alert(a);//1

这里感觉作用域链只可意会不可言传。。。。当我们在运行fn1()这个函数的时候,fn1()函数内部.var a=2发生声明前置,
此时.alert(a)输出undefined,以为只是声明前置了。并没有赋值操作。 此时就相当于在fn1()函数内部产生了一个局部变量a,这时候把2的值赋给a.但是全局变量中的a并不会因此发生变化。


隐性声明

1
2
3
4
5
6
7
var a = 1;
function fn1(){
alert(a); //1
a = 2;
}

fn1();

alert(a); //2

这个和上一题差不多,只是这里的a 是隐性声明,可以把它想象成没有声明。直接赋值。这里运行的fn1()的时候,发现找不到a了。但是不怕 我有作用域链的关系,我可以向上找。然后在全局变量中找到了a.这时候 急着要用a啊 没办法,只能用全局变量中的这个a 了。于是laert(a)输出1,然后再把2的值赋值给a.这个时候的a是全局变量。所有当我们再全局中运行alert(a)就输出2


对于一个带参数的函数

1
2
3
4
5
6
7
var a = 1;
function fn1(a){
alert(a);
a = 2;
}

fn1();

alert(a);

这里的情况又有所不同:这里的fn1函数是带有参数的,相当于这样

1
2
3
4
5
6
7
8
var a;
function fn1(a){
var a=undefined;
alert(a);
a=2;//这里a 并不是全局变量中的a哦,而是一个形参。
}

fn1();

alert(a)//1

为了证明 上面的说法。我们来看这个例子:

1
2
3
4
5
6
7
8
9
10
var c=1;
var a=1;
function fn1(a){
alert(a);//3
c=2;
a=2;
}

fn1(3);

alert(c)//2
alert(a)//1

这样就很明显啦。对于一个带有参数的函数,我只需要对其做一点点小小的”加工”。让我们来看最后一个例子


对于一个带参数的函数(基本类型)

1
2
3
4
5
6
7
var a = 1;
function fn1(a){
alert(a);
a = 2;
}

fn1(a);

alert(a);

上面这个例子可以转换成这样

1
2
3
4
5
6
7
8
var a;
function fn1(a){
var a="传进来的参数"
alert(a);//1
a=2
}

fn1(a);

alert(a);//1

这里fn1(a)相当于fn1(1);使得函数fn1中 var a=1;(这里a是基本类型的变量。传递的时候是”副本形式”,)所以第一个alert(a)输出1;然后 a=2;这时候全局变量中的a还是1,所以alert(a)输出还是1;


一晃就三月份了。陆陆续续学了那么多。感觉反而更迷茫了。。。。。学习一门语言都是这样么- -越学越觉得自己水平又多低。。。。