一、全局变量 局部变量
function test ( ){
var a = 123;
function demo(){
var b = 234;
console.log(a);
}
demo();
console.log(b);
}
test();
局部变量可以访问全局变量
全局变量不能访问局部变量
二、作用域精解
运行期上下文:
当函数执行前一刻 会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
[[scope]]:
每个js函数都是一个对象,对象都有属性和方法供我们访问,但有些不可以,这些属性仅供js引擎存取,[[scope]]就是其中一个。[[scope]]指的是我们所说的作用域,其中存储了运行期上下文的集合。
[[scope]]作用域链:
[[scope]]中储存的执行期上下文对象的集合,成链式连接。每次执行一个函数前都会创建一个执行期上下文,放在作用域顶端。查找变量就是从顶端往下扫描。
1、构建作用域过程:
function a(){
function b(){
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();
a defined --> a.[[scope]] --> 0 :GO
a doing ( b defined )–> a.[[scope]]/ b.[[scope]] --> 0 : AO , 1 : GO
a doing ( b defined )–> a.[[scope]]/ b.[[scope]] --> 0 : AO , 1 : GO
b doing --> b.[[scope]] --> 0 : AO , 1 : AO , 2 : GO
当b执行完后销毁自己的执行期上下文,b执行完意味着a也执行完毕,a销毁自己的执行期上下文,同时删除b函数。等待下一次执行a函数时创建全新的执行期上下文,构建新的作用域链。
2、作用域链下A0对象和外面的包含函数产生的AO为同一个
function a(){
function b(){
var b = 234;
a = 0;
}
var a = 123;
console.log(a); // 123
b();
console.log(a); // 0
}
var Global = 100;
a();
console.log(a); // function a(){ ...}
3、构建作用域链精解
function a(){
function b(){
function(){
}
c();
}
b();
}
a();
-
ps: ( a )( b )( c )是下标便于区分。
1、首先a被定义,生成a.[[scope]], 创建GO放在作用域里。
2、然后a执行,创建(a)AO,放在作用域顶端。与此同时b被定义,作用域里放着此时a.[[scope]]里的(a)AO、GO。
3、然后b执行,生成b.[[scope]], 创建(b)AO,放在作用域顶端。与此同时c被定义,作用域里放着此时b.[[scope]]里的(b)AO、(a)AO、GO。
4、最后c执行,生成c.[[scope]], 创建©AO,放在作用域顶端。 -
所有的(a)AO、(b)AO、 ©AO都是同一个执行期上下文
每次执行完都销毁自己的执行期上下文,然后等待再次被定义与执行。 -
从上面的过程看,最底层的函数,包含的执行期上下文越多,所以才有那两句话:
局部变量可以访问全局变量
全局变量不能访问局部变量