(一)、作用域与作用域链
了解AO和 GO 是为了解决js当中的一系列关于作用域和作用域链相关所产生的一切问题
function test(a,b){
}
console.log(test.name); //test
console.log(test.length); //2
//可以看出function也有属性,其实函数也是一种对象类型,也是一种引用类型,也是一种引用值
对象中有些属性我们是无法访问的,这些属性就是JS引擎内部固有的隐式属性
既然我们用不了,为什么我们需要去研究这些隐式属性?
因为如果不研究的话就不知道它的原理,在上层就没法更好的写代码
(1)作用域中的一个隐式属性[[scope]]
1、函数创建时,生成的一个JS内部的隐式属性,这个属性是js引擎来读取的
2、它是存储函数作用域链的容器
作用域链存储其实就是我们所说的AO(函数的执行期上下文)/ GO(全局的执行期上下文)
当函数执行完成以后,AO是要被销毁的,也就是说每次执行函数的时候会生成一个新的AO,
也就是说AO是一个即时的存储容器
一定要记住,每一个函数的作用域链都是包含GO的,每一个函数在定义的时候就包含了全局执行上下文GO,
在执行函数的前一刻形成的AO。
记住,所有的自身的AO都是排在自身的作用域的最顶端的
当外层函数被执行的时候,内层函数被定义,这是一个规律。
a函数被执行的时候,b函数被定义。
当b函数被执行之前的作用域链和a函数被执行的时候的作用域链是一样的
一定要记住,在函数被定义的时候生成作用域和作用域链,作用域链中已经存在GO了,在函数被执行的那一刻生成自己的AO
(二)、闭包
function test1(){
function test2(){
var b = 2;
console.log(a);
}
var a = 1;
return test2();
}
var c = 3;
var test3 = test1();
test1在执行的时候,test2被定义,他们两个的作用域链是完全相同的
test3里面保存的是test2,test3执行的时候相当于执行了test2,test2一执行,生成自己的AO
test1返回的是整个test2这个函数,test3执行其实就是执行test2
闭包:当内部函数被返回到外部并保存时,一定会产生闭包
闭包会产生原来的作用域链不释放
,过度的闭包可能会导致内存泄露或加载过慢。
闭包例子:
闭包可以用来做数据缓存
可以用数组返回多个函数。
supply供应 sale出售
function sunSched(){
var sunSched = '';
var operation = {
setSched: function(thing){
sunSched = thing;
},
showSched: function(){
console.log("My schedule on sunday is " + sunSched);
}
}
return operation;
}
var sunSched = sunSched();
sunSched.setSched('studying');
sunSched.showSched();
打印结果:
My schedule on sunday is studying