6.1 对象
函数也是一种对象类型 引用类型 引用值 eg:test.name test.length test.prototype 对象
->有一些属性是我们无法访问的(JS引擎内部固有的属性)eg:[[scope]]
6.2隐式属性 [[scope]]
[[scope]]
1.函数创建时,生成的一个JS内部的隐式属性
2.函数存储作用域链的容器,作用域链有AO/GO AO:函数的执行期上下文 GO:全局的执行期上下文 函数执行完成以后,AO要被销毁,也就是说AO是一个即时的存储容器
6.3作用域链
function a(){
function b(){
var b = 2;
}
var a = 1;
b();
}
var c = 3;
a();
当a函数被定义时
系统生成[[scope]]属性,[[scope]]保存该函数的作用域链,该作用域链的第0位存储当前环境下的全局执行上下期上下文GO,GO里面存储全局下的所有对象,其中包含函数a和全局变量c
function a(){}
var c = 3;
当a函数被执行时(前一刻)
作用域的顶端(第0位)存储a函数生成的函数执行期上下文AO,同时第1位存储GO。查找变量是到a函数的作用域从顶端开始依次向下查找。
function a(){
function b(){}
var a = 1;
}
var c = 3;
a();
当b函数被定义时
是在a函数环境下,所以b函数这时的作用域链就是a函数被执行期的作用域链
function a(){
function b(){}
var a = 1;
}
var c = 3;
a();
当b函数被执行时(前一刻)
生成函数b的[[scope]],存储函数b的作用域链,顶端第0位存储b函数的AO,a函数的AO和全局的GO依次向下
function a(){
function b(){
var b = 2;
}
var a = 1;
b();
}
var c = 3;
a();
当b函数被执行结束后
b函数的AO被销毁,回归被定义时的状态
当a函数执行结束后
a函数的AO被销毁的同时,b函数的[[scope]]也将不存在。 a函数回归到被定义时的状态。
function a() {
function b() {
function c() {
}
c();
}
b();
}
a();
a 定义:a.[[scope]] -> 0 : GO
a 执行:a.[[scope]] -> 0 : a->AO-> 1: GO
b 定义:b.[[scope]] -> 0 : a->AO-> 1: GO
b 执行:b.[[scope]] -> 0 : b->AO-> 1 : a->AO-> 2 : GO
c 定义:c.[[scope]] -> 0 : b->AO-> 1 : a->AO-> 2 : GO
c 执行:c.[[scope]] -> 0 : c->AO-> 1: b->AO-> 2 : a->AO -> 3 : GO
c 结束:c.[[scope]] -> 0 : b->AO-> 1 : a->AO -> 2 : GO
b 结束:b.[[scope]] -> 0 : a->AO -> 1 : GO c.[[scope]] x 没有了
a 结束:a.[[scope]] -> 0:GO b.[[scope]] x 没有了
6.4闭包
function test1() {
function test2() {
var b = 2;
console.log(a);
}
var a = 1;
return test2();
}
var c = 3;
var test3 = test1();
test3();
当test1函数被定义时
系统自动生成[[scope]]属性,[[scope]]保存该函数的作用域,该作用域的第0位存储当前环境下的全局执行期上下文GO,GO里存储全局下的所有对象,其中包含函数test1和全局变量c和test3
function test1(){}
var c = 3;
var test3 =test1();
当test1函数被执行时(前一刻)
test2被定义
function test1() {
function test2() {
}
var a = 1;
return test2();
}
var c = 3;
var test3 = test1();
当test1函数执行结束时
因为test2被返回到外部,且被全局变量test3接收。 这时的test1的AO并没有被销毁,只是把线剪断,test2的作用域链还与之相连。
当test3执行时
test2的作用域链增加自己的AO
当test3执行结束后
test2的AO被销毁,但原来test1的AO仍然存在且被test2连着
应用
- 实现累加、累减
function test() {
var n = 100;
console.log(n);
function add() {
n++;
console.log(n);
}
function reduce() {
n--;
console.log(n);
}
return [add, reduce];
}
var arr = test();
arr[0](); // 101
arr[1](); // 100
arr[1](); // 99
// 闭包也是一种数据缓存
- 实现一个面包管理器
function breadMgr(num){
var breadNum = arguments[0] || 10; // 或者用 num || 0
function supply(){
breadNum += 10;
console.log(breadNum);
}
function sale(){
breadNum -= 1;
console.log(breadNum);
}
return [supply, sale];
}
var breadMgr = breadMgr(50);
breadMgr[0]();
breadMgr[1]();
breadMgr[1]();
3.星期天计划管理
function sunSched() {
var sunSched = '';
var operation = {
setSched: function(thing) {
sunSched = thing;
},
showSched: function() {
console.log("Schedule on sunday is " + sunSched);
}
}
return operation;
}
var sunSched = sunSched();
sunSched.setSched('studying');
sunSched.setSched('walking');
sunSched.showSched();