一直以为js的闭包只是内部函数保存了一份外部函数的变量值副本,但是以下代码打破了我的认识:

function createFunctions()
{
var result = new Array(); for(var i=0;i<10;++i)
{
result[i] = function()
{
return i;
}
} return result;
} var funcs = createFunctions();
for(var i=0;i<10;++i)
{
console.log(funcs[i]());
}

  执行结果是10个10 而不是0-9

看了JS高级编程7.2.1之后才明白 变量i并不是存在于匿名函数的局部变量表,而是存储在createFunctions的活动对象表(存储参数和局部变量)中。并且在创建函数的定义过程中匿名函数只是被定义而没有被执行。直到后面输出的循环被定义的匿名函数们才得以执行,而这时候它们的活动对象表里并不存在i,然后它们就会从作用域链向上查找createFunctions的活动对象表中的i。这时i的值已经是10,因此它们的执行结果全是10。

以下代码在闭包外部再加入了一个含参数的闭包,并且在定义之后调用,传递进去当前的i。这时这层新增的闭包活动对象表中含有参数num会存储i的当前值。这样结果就是0-9了:

 function createFunctions()
{
var result = new Array(); for(var i=0;i<10;++i)
{
result[i] = function(num)
{
return function(){
return num;
}
}(i);
}
return result;
} var funcs = createFunctions();
for(var i=0;i<10;++i)
{
console.log(funcs[i]());
}

闭包的活动对象表中并不会包含this,this是当前执行上下文中的概念,会随着调用环境而变化。

 name = "global name"
var obj = {
name:"object name",
func:function()
{
return function(){
return this.name;
}
}
}
console.log(obj.func()()); var obj2 = {
name:"object name",
func:function()
{
that = this;
return function(){
return that.name;
}
}
}
console.log(obj2.func()()); var obj3 = {
name:"object name",
func:function()
{
return this.name;
}
}
console.log(obj3.func());
console.log((obj3.func)());
console.log((obj3.func = obj3.func)());

输出结果:

global name
object name
object name
object name
global name

第一个输出 因为this并不在活动对象表里,闭包在调用的地方才获得当前的this,也就是全局对象

第二个输出 因为闭包定义之前取了this存到外层函数的that变量,用that就可以得到自定义对象

第3,4个输出 没有闭包 直接输出this

第五个输出 因为赋值表达式取结果的操作把当前的上下文变成了全局的,可以当做赋值操作不属于任何对象因此得到的是全局对象

最新文章

  1. Sublime Text 3 Plugin Better!
  2. Rally的敏捷小册子
  3. Mediator(中介者)-对象行为型模式
  4. 关于TreeView的选中事件
  5. const C语言(转)
  6. uiautomator &lt;一&gt; 编译运行
  7. HTML静态网页(css样式表)
  8. 如果gen.lib.rus.ec这个电子书下载站上不去了,那就用这个吧
  9. [河南省ACM省赛-第三届] AMAZING AUCTION (nyoj 251)
  10. 使用Visual Studio Team Services持续集成(一)——构建ASP.NET Core
  11. 03-Linux的shell命令 .doc
  12. php : 文件及文件夹操作(创建、删除、移动、复制)
  13. EF SaveChanges() 报错(转载)
  14. 最大似然估计(Maximum likelihood estimation)(通过例子理解)
  15. Leetcode 860. 柠檬水找零
  16. axios请求带上cookie配置
  17. document.head.appendChild(element) 在 IE8 及以下报错
  18. Python接口测试实战4(下) - 框架完善:用例基类,用例标签,重新运行上次失败用例
  19. BZOJ4881 线段游戏(二分图+树状数组/动态规划+线段树)
  20. python3 SQLAlchemy模块使用

热门文章

  1. Android UI 绘制过程浅析(五)自定义View
  2. Python体验(07)-图形界面之菜单
  3. Java中的闪光点:ThreadLocal是线程Thead的局部变量,可替代同步机制的设计,值得学习和研究
  4. C#小程序飞行棋关卡操作
  5. 前端学习实践笔记--JavaScript深入【3】
  6. ajax options
  7. js中join函数的使用方法(js输出html标签)
  8. Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境搭建教程
  9. PowerDesigner 逆向中 Name和Comment互换
  10. Office OneNote 自动打开问题