作用域初探
1、作用域定义:变量(变量作用域又称上下文)和函数生效(能被访问)的区域
2、全局变量、局部变量
3、作用域的访问顺序
挑战性作业: 要求输入一串低于10位的数字,输出这串数字的中文大写。
eg: input: 10000 output: 壹万
eg: input: 1001010 output: 壹佰万壹仟零壹拾
作用域精解
1、[[scope]]:每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是我们所说的作用域,其中存储了执行期上下文的集合
2、作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。作用域链本质上是一个指向当前环境与上层环境的一系列变量对象的指针列表
3、执行期上下文:当函数执行时(前一刻),会创建一个称为执行期上下文的内部对象(AO)。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
AO放在作用域链的顶端
4、查找变量:从作用域的顶端依次向下查找。
例1:
function a(){
function b(){
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();
a 函数被定义时,发生如下过程:a.[[scope]] ----> 0 : GO { }
a 函数被执行时,发生如下过程:a.[[scope]] ----> 0 : AO { } 、1 :GO{ }
b 函数被创建时,发生如下过程:b.[[scope]] ----> 0 : AO { } 、1 :GO{ }
b 函数被执行时,发生如下过程:b.[[scope]] ----> 0 : AO { } 、1 :AO{ }
、 2 :AO{ }
例2:
function a(){
function b(){
var bbb = 234;
console.log(aaa);
}
var aaa = 123;
return b; //b被保存出来,demo()
}
var glob = 100;
var demo = a();
demo();
但凡是内部函数,被保存到外部,一定生成闭包
闭包
当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。
闭包小例子:
function a(){
var num = 100;
function b(){
num ++;
console.log(num);
}
return b;
}
//a 的AO被销毁
var demo = a(); //执行a,将函数b保存在demo中
demo(); //执行b,打印出101
//此时a的AO已经被销毁,第一次执行完b之后,将a的AO里面num值改为101,b的AO被销毁
demo(); //再执行b,打印出102
闭包的作用
1、实现公有变量
eg : 函数累加器
function add(){
var count = 0;
function demo(){
count ++;
sonsole.log(count);
}
return demo();
}
var counter = add();
counter();
counter();
counter();
function test(){
var num = 100;
function a(){
num ++;
console.log(num);
}
function b(){
num --;
console.log(num);
}
return [a,b];
}
var myArr = test();
myArr[0](); //打印101
myArr[1]{}; //打印100
//a和b共用一个test的AO
2、可以做缓存(存储结构)
eg : eater
function eater(){
var food = "";
var obj = {
eat : function (){
console.log("i am eating" + food);
food = "";
}, //对象的方法
push : function(myFood){
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push('banana');
eater1.eat();
3、可以实现封装,属性私有化
eg : Person();
4、模块化开发,防止污染全局变量