文章 评论 浏览 31
var scope = "global scope"; function checkscope() { var scope = "local scope"; function f() { return scope; } return f; } checkscope()();
1.执行全局代码,创建全局执行上下文,全局上下文被压入执行上下文栈:
ECStack = [ globalContext ]
2.开始执行代码,全局上下文初始化:
globalContext = { VO: [ global ], Scope: [ globalContext.VO ], this: globalContext.VO }
3.初始化的同时,checkscope函数被创建,保存作用域链到内部属性[[scope]]:
checkscope
[[scope]]
checkscope.[[scope]] = [ globalContext.VO ];
4.开始执行checkscope函数,创建checkscope函数执行上下文,并将checkscope函数上下文压入执行上下文栈:
ECStack = [ checkscopeContext, globalContext ];
5.checkscope函数上下文初始化:
checkscopeContext = { AO: { arguments: { length: 0 }, scope: undefined, f: reference to function f(){} }, Scope: [AO, globalContext.VO], this: undefined }
初始化的同时, f函数被创建,保存作用域链到 f函数的内部属性[[scope]]:
f函数
f.[[scope]] = [checkscopeContext.AO, globalContext.VO]
6.checkscope函数执行,随着函数的执行,修改AO的值,所以此时checkscopeContext变更为:
AO
checkscopeContext
checkscopeContext = { AO: { arguments: { length: 0 }, scope: "local scope", f: reference to function f(){} }, Scope: [AO, globalContext.VO], this: checkscopeContext.AO }
接着返回了f函数.
7.checkscope 函数执行完毕,checkscope 执行上下文从执行上下文栈中弹出:
ECStack = [ globalContext ];
8.开始执行f 函数,创建f函数执行上下文,并将f函数上下文压入执行上下文栈:
f 函数
f
ECStack = [ fContext, globalContext ];
9.f函数上下文初始化:
fContext = { AO: { arguments: { length: 0 } }, Scope: [AO, checkscopeContext.AO, globalContext.VO], this: undefined }
10.f函数执行,沿着作用域链查找scope 的值,找到并返回了scope.
scope
可是当 f 函数执行的时候,checkscope 函数上下文已经被销毁了(即从执行上下文栈中被弹出),怎么还会读取到 checkscope 作用域下的 scope 值呢?
checkscope 函数
这是因为 checkscope 函数执行上下文初始化时,f 函数同时被创建,保存作用域链到 f 函数的内部属性[[scope]],所以即使checkscope函数执行完毕,被弹出执行上下文栈,但是checkscopeContext.AO 依然存在于 f 函数的内部属性[scope]]中:
checkscopeContext.AO
[scope]]
所以在f 函数执行的时候仍然可以通过 f 函数的作用域链能找到scope.所以这里就产生了闭包:
11.f 函数执行完毕,f 执行上下文从执行上下文栈中弹出:
应该是 a.b.c.d 比 a['b']['c']['d'] 性能高点,后者还要考虑 [ ] 中是变量的情况,再者,从两种形式的结构来看,显然编译器解析前者要比后者容易些,自然也就快一点。下图是两者的 AST 对比:
a.b.c.d
a['b']['c']['d']
[ ]
文章 0 评论 0
接受
分析第二段代码
1.执行全局代码,创建全局执行上下文,全局上下文被压入执行上下文栈:
2.开始执行代码,全局上下文初始化:
3.初始化的同时,
checkscope
函数被创建,保存作用域链到内部属性[[scope]]
:4.开始执行
checkscope
函数,创建checkscope
函数执行上下文,并将checkscope
函数上下文压入执行上下文栈:5.
checkscope
函数上下文初始化:checkscope
函数作用域链顶端。初始化的同时,
f函数
被创建,保存作用域链到f函数
的内部属性[[scope]]
:6.
checkscope
函数执行,随着函数的执行,修改AO
的值,所以此时checkscopeContext
变更为:接着返回了
f函数
.7.
checkscope
函数执行完毕,checkscope
执行上下文从执行上下文栈中弹出:8.开始执行
f 函数
,创建f
函数执行上下文,并将f
函数上下文压入执行上下文栈:9.
f
函数上下文初始化:f 函数
作用域链顶端。10.
f
函数执行,沿着作用域链查找scope
的值,找到并返回了scope
.可是当
f 函数
执行的时候,checkscope 函数
上下文已经被销毁了(即从执行上下文栈中被弹出),怎么还会读取到checkscope
作用域下的scope
值呢?这是因为
checkscope
函数执行上下文初始化时,f 函数
同时被创建,保存作用域链到f 函数
的内部属性[[scope]]
,所以即使checkscope
函数执行完毕,被弹出执行上下文栈,但是checkscopeContext.AO
依然存在于f 函数
的内部属性[scope]]
中:所以在
f 函数
执行的时候仍然可以通过f 函数
的作用域链能找到scope
.所以这里就产生了闭包:11.
f
函数执行完毕,f
执行上下文从执行上下文栈中弹出:JavaScript 深入之执行上下文