一、作用域作用域链
- 对象中,有些属性是我们无法访问的,JS引擎内部固有的隐式属性
- 隐式属性 [[scope]]
- 它是函数创建时,就生成的一个JS内部隐式属性
- 它是用于存储函数的作用域链的容器[scope chain],作用域链里存储的就是AO GO
- AO:函数执行期上下文,函数执行完后,函数体内没有东西被函数以外的东西所占用,那么这个AO就会被销毁;AO是一个即时的存储的容器
GO:全局执行期上下文
// AO GO -> 跟作用域作用域链相关所产生的一切问题// AO:函数执行期上下文,跟函数相关// 对象var obj = {name: 'liangyu',age: 10,height: 170,weight: 55}console.log(obj.name);// 函数也是对象function test(a, b){// 打印函数的名字console.log(test.name);// 打印函数的形参个数console.log(test.length);}// 对象中,有些属性是我们无法访问的,JS引擎内部固有的隐式属性// 隐式属性 [[scope]]// 1. 它是函数创建时,就生成的一个JS内部隐式属性// 2. 它是用于存储函数的作用域链的容器[scope chain],作用域链里存储的就是AO GO// AO:函数执行期上下文,函数执行完后,函数体内没有东西被函数以外的东西所占用,那么这个AO就会被销毁;AO是一个即时的存储的容器// GO:全局执行期上下文function a(){function b(){var b = 3;}var a = 1;b();}var c = 3;a();
每一个函数的作用域链上都有GO


当外层函数执行时,内层函数被定义





函数在刚开始被定义的时候,拿的都是上级的环境;只有当函数执行的时候,才会形成自己的AO;自己的AO要排在最顶端全局执行的前一刻生成 GO;在生成GO的时候,全局的函数已经声明和定义了
全局执行
1. 找变量声明
2. 找函数声明并赋值// GO = {// test2: function test2(){}// }test2();function test2(){}// GO = {// test1: undefined// }test1(); // 报错var test1 = function(){}
函数在定义的时候就已经生成隐式属性 [[scope]]了,作用域里面最开始存储的是GO,函数在执行前一刻会形成自己的AO,并且排在作用域最顶端
// 函数在定义的时候就已经生成隐式属性 [[scope]]了,作用域里面最开始存储的是GO,函数在执行时会形成自己的AO,并且排在作用域最顶端function test2(){function test3(){}}test2();// GO = {// test2: function test2(){}// }// AO = {// test3: function test3(){}// }
二、闭包基础
闭包:内部函数返回到外部并被占用时,就一定会产生闭包;闭包会导致原来的作用域链不被释放;过渡的闭包可能会导致内存泄漏,或者加载过慢
// 闭包基础// 内部函数返回到外部并保存时,一定会产生闭包;闭包会导致原来的作用域链不被释放// 过渡的闭包可能会导致内存泄漏,或者加载过慢function test1(){function test2(){var b = 2;a = 2;console.log(a);}var a = 1;return test2;}var c = 3;var test3 = test1();test3();

三、闭包的简单应用
3.1、应用一:利用数组返回闭包
利用闭包原理实现累加累减
// 闭包应用一// 利用闭包原理实现累加累减function func(){var n = 100;function add(){n++;console.log(n);}function reduce(){n--;console.log(n);}return [add, reduce];}var compute = func();compute[0]();compute[0]();compute[1]();
3.2、应用二:利用数组返回闭包
利用闭包原理实现一个面包管理器
// 利用闭包原理实现一个面包管理器function breadMgr(num){var breadNum = arguments[0] || 10;function supply(){breadNum += 10;console.log(breadNum);}function sale(){breadNum--;console.log(breadNum);}return [supply, sale];}var breadMgr = breadMgr(50);breadMgr[0]();breadMgr[1]();breadMgr[1]();
3.3、应用三:利用对象返回闭包
利用闭包做一个星期天安排计划
// 利用闭包做一个星期天安排计划function sunSchedule(){var sunSchedule = '';var operation = {setSchedule: function(thing){sunSchedule = thing;console.log(sunSchedule);},showSchedule: function(){console.log('my schedule on sunday is' + ' ' + sunSchedule);}}return operation;}var sunSchedule = sunSchedule();sunSchedule.setSchedule('walking');sunSchedule.showSchedule();
