Contents
  1. 1. 变量的预解析

首先 ,函数作用域 or 块级作用域 ???

块级是指c/c++内 只要存在花括号,就是独立的作用域
而js是函数作用域,故名思议:
只有函数内部才会生成独立的作用域

1
2
3
4
5
var a=0;
(function(){
a=1;
}());
console.log(a);

作用域有什么存在感呢?
在一个作用域,不论是就处于该作用域还是处于子函数内部,都有读取和修改该变量的权力,如上

因此 ,我们来看一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a = 0;
(function(){
a=1;
(function(){
a=2;
(function(){
a=3;
(function(){
a=4;
console.log(a);
}());
console.log(a);
}());
console.log(a);
}();
console.log(a);
}());
console.log(a);

此处的a会是几呢???答案是4,肯定很明显,我要问的问题是问什么会是4?你能答上来吗
如上的问题的答案其实是这样的:
从最外层函数开始,给a申明了作用域,并不断的在内部函数里面修改他的值。
其实就是使得变量a变成能够被底下所有函数访问和修改的变量

该例子中,因为console.log是在自执行函数的下面执行的,故5个console.log(a)执行的顺序是从上到下依次执行。

而在第一个console.log执行时,a以及变为了4,而所有函数都是共享这一个a的,所以大家都输出4

这个例子变一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a = 0;
(function(){
var a=1;
(function(){
var a=2;
(function(){
var a=3;
(function(){
var a=4;
console.log(a);
}());
console.log(a);
}());
console.log(a);
}())
console.log(a);
}());
console.log(a);

给每个函数内部都重新申明一下a,表明这个a是我这个函数作用域内部的,我改了你们没关系,所以执行下来应该是4,3,2,1,

接下来

1
2
3
4
5
6
7
8
9
10
11
12
function a(){
n=0;
b();
function b(){
n=1;
getn();
}
function getn(){
console.log(n);
}
}
a();

n会是几呢
方法getn在a内创建在b内执行,n在两个作用域下都有自己的形态,
而最终获取到n其实是1,说明方法的作用域是在执行时创建的,而不是在声明时创建的
再来闭包那一节讲到的例子

1
2
3
4
5
6
for(var i=0;i<5;i++){
var index = i;
buttons[index].onclick=function(){
console.log(index);
}
}

根据index作用域链
在 “console.log(index)”的时候,js引擎首先会在 onclick的函数内部找,显然他没找到index的声明,故他继续往上找,在for循环的内部找到了index的声明,然而,for循环是没有独立作用域的,故 index 的值随着for循环也依次被替换了,导致了index其实是最后的i,即为4

变量的预解析

声明是变量的预解析???

变量的预解析就是你还没有在一个作用域内部,你声明了一个变量,则在这个作用域内部,这个变量声明之前,javascript自动帮你的变量声明了,并且赋值为 undefined
接下来举个栗子,很简单

1
console.log(a);

这会报一个错,因为你上下文中无法找到a的声明,所以他是not found

1
2
console.log(b);
var b=1;

此处。。你在声明b之前,就去获取b,然而他不会报错了。由于变量声明提前的缘故,b已经声明了,不过还没赋值,所以是undefined

1
2
var c=1;
console.log(c)

嗯 这次终于对了是吧 先声明后调用,声明之前不要出现对该变量的获取

还有一个栗子

1
2
3
4
5
var a=1;
(function(){
console.log(a);
var a=1;
}());

尊崇作用域内有效的规则,这个a肯定是undefined

其实那个b的例子本质上应该是这样的

1
2
3
var b = undefined;
console.log(b);
b=1;

变量的预解析,实质上就是声明提前,赋值却还在那个位置

谢谢阅读,如讲述存在问题还请指正 aipashang@sohu.com

Contents
  1. 1. 变量的预解析