作用域
作用域:从表层上讲:就是在函数的里层作用域可以访问到外层作用域的变量。从底层上讲:就是在函数被执行的前一刻,会创建自己的[[scope]]对象。[[scope]]会保存当前作用域和上层作用域的变量和方法。函数自身的执行期上下文放在最顶端,上层作用域的上下文往下依次排列,构成作用域链。
作用域链:在函数被执行的前一刻,会创建自己的[[scope]]对象。[[scope]]会保存当前作用域和上层作用域的变量和方法。函数自身的AO放在最顶端,上层作用域的上下文往下依次排列,构成作用域链。(scope chain 作用域链)。解释2:作用域链 即把AO, GO按次序排列起来,形成的链式关系叫作用域链。
用作用域链理解函数找变量的过程:函数在找变量的时候,是从作用域链的最顶端开始找的,每个函数自己的AO都是排在作用域链的最顶端,所以这就解释了全局和局部有同名变量时, 函数会使用自己的AO里面的局部变量。
GO:全局执行期上下文。
GO的形式:
GO ={
this: window,
window: obj,
document: obj,
...
}
AO:函数执行期上下文。 函数执行完成后,AO是要销毁的。AO是一个即时的存储容器,每次函数执行的时候,都会创建一个新的AO。
AO的形式:
AO = {
this:window,
arguments:[],
...
}
AO,GO的作用: 理解作用域、作用域链的特性。
GO = {
window:
this:
document:
}
A0 = {
window:
this:
document:
}
函数对象的属性:函数也是一种引用类型/对象类型,它具有自己的属性。
函数的属性:test.name, test.length, test.prototype等。[[scope]]是函数的内置属性,外界无法直接访问该对象。
对象的内置属性:有些属性是我们无法访问的,可以理解为JS引擎内部固有的隐式属性。
关于[[scope]]的理解:1. [[scope]]函数创建时,生成的一个JS内部的隐式属性,只能由JS引擎读取。2. 它是用来存储作用域链:
闭包的几个小点:当内部函数被返回到外部并保存时,一定会产生闭包。闭包会使原来的作用域不释放。过度的闭包可能会导致内存泄漏,或加载过慢。闭包是一个特性,是一种因为内部函数返回被外部变量保存而产生的一种作用域链不释放的现象。
测试题:
1. 手写闭包:
function test(){
var a = 100;
function add(){
a++;
console.log(a);
}
function reduce(){
a--;
console.log(a);
}
return [add,reduce];
}
var arr = test();
arr[0]();
arr[1]();
//101 100
2. 手写闭包2:
function test(){
var count = 0;
return function add(){
count++;
console.log(count);
}
}
var tt = test();
tt();
//1