SlideShare a Scribd company logo
1 of 14
Download to read offline
Javascript Closures

    Javascript 闭包
Every function is an object
在JavaScript中每个函数都是对象。
(说了等于没说)怎么理解这句话?
敲在编辑器中的代码只是代码,被js引擎导入以后的代码中
的每个函数定义就成为了对象。
或者说就被js engine表示成了对象,更进一步说是
Function的实例。
这些函数对象和其他对象一样也包含了你能访问的属性,比
如name, length, prototype。也包括了你不能通过代码访
问的内部属性。其中一个属性就是[[Scope]],在ECMA-262,
Third Edition中定义。
创建函数对象时生成作用域链
function add(num1, num2) {
  var sum = num1 + num2;
  return sum;
}
When the function is created, its scope chain is populated
with global object     这个集合就被称为函
                                           这个集合由变量对象
   [[Scope]]属性指向一                         variable object组
                       数的作用域链
   个集合                                    成。




                    作用域链就决定了函数可以
  js engine读到函数定义,创
                    访问到的数据。
  建函数对象,生成作用域
                                         这个全局变量对象由一些键值
  链。
                                         对组成key-value pairs
执行函数时

var total = add(5, 10);
执行add函数时,js engine就会为该函数创建一个内部对
象--执行上下文execution context。同一个函数每次执行
时都会创建一个EC,这个EC定义了函数在这次执行时的环
境,所以称它为执行上下文。当函数执行完以后,该EC就会
被销毁,它所占内存就被释放。
激活对象Activation object

执行上下文execution context 简称EC
EC有自己的scope chain,该SC的作用是什么呢?
用来identifier resolution,也就是找到变量名,函数名所指的
对象。那EC的SC怎么创建,初始化些什么内容呢?
函数创建时生成的SC就派上用场了。函数SC中的变量对象中
的键值对就被拷贝进EC的SC中的变量对象中。
这个激活对象为这次函数执行准备了所有的局部变量,命名
参数,arguments对象和this对象。这个激活对象被放置在
SC的第一个位置,因此最先被找到。当EC销毁时,这个激活
对象也被销毁。(这句话不够准确,应该是当这个激活对象
没有引用时,才会被销毁。这在讲到闭包时会再次提到。)
理解闭包:内嵌函数nested function

var scope = "global";               // 全局变量scope
function checkscope() {
  var scope = "local";               // 局部变量scope
  function f() { return scope; }    // 返回变量scope的值
  return f;                        // 返回内嵌函数
}
var f = checkscope();              // 变量 f 指向内嵌函数实
例
f();
var f = checkscope();
函数checkscope执行,返回内嵌函数,该内嵌函数也是一个
对象(记得吗?everything is object),更具体的说是一
个函数实例对象。这个对象也有Scope属性,指向scope
chain,而且这个SC的variable object就是checkscope函数
的变量对象,js的设计很神奇!这样做很有趣,但带来了副
作用。
执行内嵌函数
f = checkscope(); f();
当执行这个内嵌函数时,同样EC会被创建,激活对象会被创建,并被置于SC的最
前位置。内嵌函数访问scope,根据ID解析规则,第2个变量对象中的scope变量
被找到,所以返回"local"。因为scope chain的缘故,函数外部的代码不能访问
函数内部的局部变量,这些变量就好像被函数“关闭”了。但内嵌函数可以访问
它的外部函数的局部变量,称这种内嵌函数为“闭包” closures。
var uniqueInteger = (function() {        // Define and invoke
                var counter = 0; // Private state of function below
                return function() { return counter++; };
             }());
uniqueInteger(); // ==> 0
uniqueInteger(); // ==> 1
function counter() {
   var n = 0;
   return {
      count: function() { return n++; },
      reset: function() { n = 0; }
   };
}
var c = counter(), d = counter(); // Create two counters
c.count()                    // => 0
d.count()                    // => 0: they count independently
c.reset()                   // reset() and count() methods share state
c.count()                    // => 0: because we reset c
d.count()                    // => 1: d was not reset
function addPrivateProperty(o, name, predicate) {
  var value; // This is the property value
  // The getter method simply returns the value.
  o["get" + name] = function() { return value; };
  // The setter method stores the value or throws an exception if
  // the predicate rejects the value.
  o["set" + name] = function(v) {
      if (predicate && !predicate(v))
          throw Error("set" + name + ": invalid value " + v);
      else
          value = v;
  };
}
var o = {}; // Here is an empty object
addPrivateProperty(o, "Name", function(x) { return typeof x == "string"; });
o.setName("Frank");          // Set the property value
console.log(o.getName()); // Get the property value
o.setName(0);               // Try to set a value of the wrong type
function constfunc(v) { return function() { return v; }; }
var funcs = [];
for(var i = 0; i < 10; i++) funcs[i] = constfunc(i);
funcs[5]()   // => 5
function constfuncs() {
  var funcs = [];
  for(var i = 0; i < 10; i++)
     funcs[i] = function() { return i; };
  return funcs;
}
var funcs =
constfuncs();
funcs[5]();
Another thing to remember when writing closures is that this is a JavaScript
keyword,not a variable. As discussed earlier, every function invocation has a
this value, and a closure cannot access the this value of its outer function
unless the outer function has saved that value into a variable:
var self = this; // Save this value in a variable for use by nested funcs.
The arguments binding is similar. This is not a language keyword, but it is
automatically declared for every function invocation. Since a closure has
its own binding for arguments, it cannot access the outer function’s
arguments array unless the outer func-tion has saved that array into a variable
by a different name:
var outerArguments = arguments; // Save for use by nested functions

More Related Content

What's hot

改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法crasysatan
 
About closure
About closureAbout closure
About closureotakustay
 
The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)jeffz
 
Hello Javascript
Hello JavascriptHello Javascript
Hello JavascriptBaidu, Inc.
 
Scala function-and-closures
Scala function-and-closuresScala function-and-closures
Scala function-and-closureswang hongjiang
 
Javascript share
Javascript shareJavascript share
Javascript shareXu Mac
 
jQuery源码学习
jQuery源码学习jQuery源码学习
jQuery源码学习fangdeng
 
Wind.js无障碍调试与排错
Wind.js无障碍调试与排错Wind.js无障碍调试与排错
Wind.js无障碍调试与排错jeffz
 
Js对象及函数式编程乱步
Js对象及函数式编程乱步Js对象及函数式编程乱步
Js对象及函数式编程乱步Pierre Woo
 
Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法yiditushe
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7Justin Lin
 
潜力无限的编程语言Javascript
潜力无限的编程语言Javascript潜力无限的编程语言Javascript
潜力无限的编程语言Javascriptjay li
 
Ecmascript
EcmascriptEcmascript
Ecmascriptjay li
 
Js的国(转载)
Js的国(转载)Js的国(转载)
Js的国(转载)Leo Hui
 
JavaScript现代化排错实践
JavaScript现代化排错实践JavaScript现代化排错实践
JavaScript现代化排错实践jeffz
 

What's hot (19)

改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法
 
About closure
About closureAbout closure
About closure
 
泛型总结
泛型总结泛型总结
泛型总结
 
The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)
 
functional-scala
functional-scalafunctional-scala
functional-scala
 
Hello Javascript
Hello JavascriptHello Javascript
Hello Javascript
 
前端测试
前端测试前端测试
前端测试
 
Scala function-and-closures
Scala function-and-closuresScala function-and-closures
Scala function-and-closures
 
Javascript share
Javascript shareJavascript share
Javascript share
 
jQuery源码学习
jQuery源码学习jQuery源码学习
jQuery源码学习
 
Wind.js无障碍调试与排错
Wind.js无障碍调试与排错Wind.js无障碍调试与排错
Wind.js无障碍调试与排错
 
Js对象及函数式编程乱步
Js对象及函数式编程乱步Js对象及函数式编程乱步
Js对象及函数式编程乱步
 
Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7lambda/closure – JavaScript、Python、Scala 到 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
 
JS2
JS2JS2
JS2
 
潜力无限的编程语言Javascript
潜力无限的编程语言Javascript潜力无限的编程语言Javascript
潜力无限的编程语言Javascript
 
Ecmascript
EcmascriptEcmascript
Ecmascript
 
Js的国(转载)
Js的国(转载)Js的国(转载)
Js的国(转载)
 
JavaScript现代化排错实践
JavaScript现代化排错实践JavaScript现代化排错实践
JavaScript现代化排错实践
 

Viewers also liked

Tutorial bergabung
Tutorial bergabungTutorial bergabung
Tutorial bergabungAjhie Soeryo
 
Tutorial bergabung jeunesse
Tutorial bergabung jeunesseTutorial bergabung jeunesse
Tutorial bergabung jeunesseAjhie Soeryo
 
ACRONYMS OF BROADCAST MEDIA
ACRONYMS OF BROADCAST MEDIAACRONYMS OF BROADCAST MEDIA
ACRONYMS OF BROADCAST MEDIAm_isbah
 
Java script closures
Java script closuresJava script closures
Java script closuresskywalker1114
 
Untitled presentation
Untitled presentationUntitled presentation
Untitled presentationAndrew Brewer
 
Teresa Crash Assignment
Teresa Crash AssignmentTeresa Crash Assignment
Teresa Crash AssignmentTeresa Lai
 
Skin clinic Mumbai
Skin clinic MumbaiSkin clinic Mumbai
Skin clinic MumbaiCosderma
 
Connect & combine
Connect & combineConnect & combine
Connect & combineeoherlihy
 
Creativity Assignment 2
Creativity Assignment 2Creativity Assignment 2
Creativity Assignment 2eoherlihy
 
Muhammed Roobas Oliyath's Profile
Muhammed Roobas Oliyath's ProfileMuhammed Roobas Oliyath's Profile
Muhammed Roobas Oliyath's ProfileRoobas Oliyath
 
Hyaluronic acid anti-ageing syrum
Hyaluronic acid anti-ageing syrumHyaluronic acid anti-ageing syrum
Hyaluronic acid anti-ageing syrumCosderma
 
Newderma skin clinic Mira road
Newderma skin clinic Mira roadNewderma skin clinic Mira road
Newderma skin clinic Mira roadCosderma
 
cosderma chemical peels
cosderma chemical peels cosderma chemical peels
cosderma chemical peels Cosderma
 

Viewers also liked (14)

Tutorial bergabung
Tutorial bergabungTutorial bergabung
Tutorial bergabung
 
Tutorial bergabung jeunesse
Tutorial bergabung jeunesseTutorial bergabung jeunesse
Tutorial bergabung jeunesse
 
ACRONYMS OF BROADCAST MEDIA
ACRONYMS OF BROADCAST MEDIAACRONYMS OF BROADCAST MEDIA
ACRONYMS OF BROADCAST MEDIA
 
Java script closures
Java script closuresJava script closures
Java script closures
 
Untitled presentation
Untitled presentationUntitled presentation
Untitled presentation
 
Presentasi
PresentasiPresentasi
Presentasi
 
Teresa Crash Assignment
Teresa Crash AssignmentTeresa Crash Assignment
Teresa Crash Assignment
 
Skin clinic Mumbai
Skin clinic MumbaiSkin clinic Mumbai
Skin clinic Mumbai
 
Connect & combine
Connect & combineConnect & combine
Connect & combine
 
Creativity Assignment 2
Creativity Assignment 2Creativity Assignment 2
Creativity Assignment 2
 
Muhammed Roobas Oliyath's Profile
Muhammed Roobas Oliyath's ProfileMuhammed Roobas Oliyath's Profile
Muhammed Roobas Oliyath's Profile
 
Hyaluronic acid anti-ageing syrum
Hyaluronic acid anti-ageing syrumHyaluronic acid anti-ageing syrum
Hyaluronic acid anti-ageing syrum
 
Newderma skin clinic Mira road
Newderma skin clinic Mira roadNewderma skin clinic Mira road
Newderma skin clinic Mira road
 
cosderma chemical peels
cosderma chemical peels cosderma chemical peels
cosderma chemical peels
 

Similar to Java script closures

Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非Tony Deng
 
用Jquery实现拖拽层
用Jquery实现拖拽层用Jquery实现拖拽层
用Jquery实现拖拽层yiditushe
 
Java Script 引擎技术
Java Script 引擎技术Java Script 引擎技术
Java Script 引擎技术bigqiang zou
 
Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验QLeelulu
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型keelii
 
基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程zhangdaiping
 
Keep your code clean
Keep your code cleanKeep your code clean
Keep your code cleanmacrochen
 
JavaScript Advanced Skill
JavaScript Advanced SkillJavaScript Advanced Skill
JavaScript Advanced Skillfirestoke
 
J2ee面试知识
J2ee面试知识J2ee面试知识
J2ee面试知识yiditushe
 
學好 node.js 不可不知的事
學好 node.js 不可不知的事學好 node.js 不可不知的事
學好 node.js 不可不知的事Ben Lue
 
Ejb工作原理学习笔记
Ejb工作原理学习笔记Ejb工作原理学习笔记
Ejb工作原理学习笔记yiditushe
 
Javascript 性能优化总结.docx
Javascript 性能优化总结.docxJavascript 性能优化总结.docx
Javascript 性能优化总结.docxbaixingfa
 
Ian 20151002 es2015
Ian 20151002 es2015Ian 20151002 es2015
Ian 20151002 es2015LearningTech
 
jQuery底层架构
jQuery底层架构jQuery底层架构
jQuery底层架构fangdeng
 
Script with engine
Script with engineScript with engine
Script with engineWebrebuild
 
程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號鍾誠 陳鍾誠
 
程式人雜誌 2015年五月
程式人雜誌 2015年五月程式人雜誌 2015年五月
程式人雜誌 2015年五月鍾誠 陳鍾誠
 
由一个简单的程序谈起--之四
由一个简单的程序谈起--之四由一个简单的程序谈起--之四
由一个简单的程序谈起--之四yiditushe
 

Similar to Java script closures (20)

Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
 
用Jquery实现拖拽层
用Jquery实现拖拽层用Jquery实现拖拽层
用Jquery实现拖拽层
 
Java Script 引擎技术
Java Script 引擎技术Java Script 引擎技术
Java Script 引擎技术
 
Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验
 
前端测试
前端测试前端测试
前端测试
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
 
基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程基于原型的JavaScript面向对象编程
基于原型的JavaScript面向对象编程
 
Keep your code clean
Keep your code cleanKeep your code clean
Keep your code clean
 
JavaScript Advanced Skill
JavaScript Advanced SkillJavaScript Advanced Skill
JavaScript Advanced Skill
 
J2ee面试知识
J2ee面试知识J2ee面试知识
J2ee面试知识
 
學好 node.js 不可不知的事
學好 node.js 不可不知的事學好 node.js 不可不知的事
學好 node.js 不可不知的事
 
Js培训
Js培训Js培训
Js培训
 
Ejb工作原理学习笔记
Ejb工作原理学习笔记Ejb工作原理学习笔记
Ejb工作原理学习笔记
 
Javascript 性能优化总结.docx
Javascript 性能优化总结.docxJavascript 性能优化总结.docx
Javascript 性能优化总结.docx
 
Ian 20151002 es2015
Ian 20151002 es2015Ian 20151002 es2015
Ian 20151002 es2015
 
jQuery底层架构
jQuery底层架构jQuery底层架构
jQuery底层架构
 
Script with engine
Script with engineScript with engine
Script with engine
 
程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號
 
程式人雜誌 2015年五月
程式人雜誌 2015年五月程式人雜誌 2015年五月
程式人雜誌 2015年五月
 
由一个简单的程序谈起--之四
由一个简单的程序谈起--之四由一个简单的程序谈起--之四
由一个简单的程序谈起--之四
 

Java script closures

  • 1. Javascript Closures Javascript 闭包
  • 2. Every function is an object 在JavaScript中每个函数都是对象。 (说了等于没说)怎么理解这句话? 敲在编辑器中的代码只是代码,被js引擎导入以后的代码中 的每个函数定义就成为了对象。 或者说就被js engine表示成了对象,更进一步说是 Function的实例。 这些函数对象和其他对象一样也包含了你能访问的属性,比 如name, length, prototype。也包括了你不能通过代码访 问的内部属性。其中一个属性就是[[Scope]],在ECMA-262, Third Edition中定义。
  • 3. 创建函数对象时生成作用域链 function add(num1, num2) { var sum = num1 + num2; return sum; } When the function is created, its scope chain is populated with global object 这个集合就被称为函 这个集合由变量对象 [[Scope]]属性指向一 variable object组 数的作用域链 个集合 成。 作用域链就决定了函数可以 js engine读到函数定义,创 访问到的数据。 建函数对象,生成作用域 这个全局变量对象由一些键值 链。 对组成key-value pairs
  • 4. 执行函数时 var total = add(5, 10); 执行add函数时,js engine就会为该函数创建一个内部对 象--执行上下文execution context。同一个函数每次执行 时都会创建一个EC,这个EC定义了函数在这次执行时的环 境,所以称它为执行上下文。当函数执行完以后,该EC就会 被销毁,它所占内存就被释放。
  • 5. 激活对象Activation object 执行上下文execution context 简称EC EC有自己的scope chain,该SC的作用是什么呢? 用来identifier resolution,也就是找到变量名,函数名所指的 对象。那EC的SC怎么创建,初始化些什么内容呢? 函数创建时生成的SC就派上用场了。函数SC中的变量对象中 的键值对就被拷贝进EC的SC中的变量对象中。 这个激活对象为这次函数执行准备了所有的局部变量,命名 参数,arguments对象和this对象。这个激活对象被放置在 SC的第一个位置,因此最先被找到。当EC销毁时,这个激活 对象也被销毁。(这句话不够准确,应该是当这个激活对象 没有引用时,才会被销毁。这在讲到闭包时会再次提到。)
  • 6. 理解闭包:内嵌函数nested function var scope = "global"; // 全局变量scope function checkscope() { var scope = "local"; // 局部变量scope function f() { return scope; } // 返回变量scope的值 return f; // 返回内嵌函数 } var f = checkscope(); // 变量 f 指向内嵌函数实 例 f();
  • 7. var f = checkscope(); 函数checkscope执行,返回内嵌函数,该内嵌函数也是一个 对象(记得吗?everything is object),更具体的说是一 个函数实例对象。这个对象也有Scope属性,指向scope chain,而且这个SC的variable object就是checkscope函数 的变量对象,js的设计很神奇!这样做很有趣,但带来了副 作用。
  • 8. 执行内嵌函数 f = checkscope(); f(); 当执行这个内嵌函数时,同样EC会被创建,激活对象会被创建,并被置于SC的最 前位置。内嵌函数访问scope,根据ID解析规则,第2个变量对象中的scope变量 被找到,所以返回"local"。因为scope chain的缘故,函数外部的代码不能访问 函数内部的局部变量,这些变量就好像被函数“关闭”了。但内嵌函数可以访问 它的外部函数的局部变量,称这种内嵌函数为“闭包” closures。
  • 9. var uniqueInteger = (function() { // Define and invoke var counter = 0; // Private state of function below return function() { return counter++; }; }()); uniqueInteger(); // ==> 0 uniqueInteger(); // ==> 1
  • 10. function counter() { var n = 0; return { count: function() { return n++; }, reset: function() { n = 0; } }; } var c = counter(), d = counter(); // Create two counters c.count() // => 0 d.count() // => 0: they count independently c.reset() // reset() and count() methods share state c.count() // => 0: because we reset c d.count() // => 1: d was not reset
  • 11. function addPrivateProperty(o, name, predicate) { var value; // This is the property value // The getter method simply returns the value. o["get" + name] = function() { return value; }; // The setter method stores the value or throws an exception if // the predicate rejects the value. o["set" + name] = function(v) { if (predicate && !predicate(v)) throw Error("set" + name + ": invalid value " + v); else value = v; }; } var o = {}; // Here is an empty object addPrivateProperty(o, "Name", function(x) { return typeof x == "string"; }); o.setName("Frank"); // Set the property value console.log(o.getName()); // Get the property value o.setName(0); // Try to set a value of the wrong type
  • 12. function constfunc(v) { return function() { return v; }; } var funcs = []; for(var i = 0; i < 10; i++) funcs[i] = constfunc(i); funcs[5]() // => 5
  • 13. function constfuncs() { var funcs = []; for(var i = 0; i < 10; i++) funcs[i] = function() { return i; }; return funcs; } var funcs = constfuncs(); funcs[5]();
  • 14. Another thing to remember when writing closures is that this is a JavaScript keyword,not a variable. As discussed earlier, every function invocation has a this value, and a closure cannot access the this value of its outer function unless the outer function has saved that value into a variable: var self = this; // Save this value in a variable for use by nested funcs. The arguments binding is similar. This is not a language keyword, but it is automatically declared for every function invocation. Since a closure has its own binding for arguments, it cannot access the outer function’s arguments array unless the outer func-tion has saved that array into a variable by a different name: var outerArguments = arguments; // Save for use by nested functions