SlideShare a Scribd company logo
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 (19)

PPT
改善程序设计技术的50个有效做法
crasysatan
 
PPTX
About closure
otakustay
 
DOC
泛型总结
wang hongjiang
 
PDF
The Evolution of Async Programming (GZ TechParty C#)
jeffz
 
PDF
functional-scala
wang hongjiang
 
PDF
Hello Javascript
Baidu, Inc.
 
PPTX
前端测试
frontwindysky
 
PPT
Scala function-and-closures
wang hongjiang
 
PPTX
Javascript share
Xu Mac
 
PPTX
jQuery源码学习
fangdeng
 
PDF
Wind.js无障碍调试与排错
jeffz
 
PDF
Js对象及函数式编程乱步
Pierre Woo
 
PDF
Jni攻略之八――操作对象的构造方法
yiditushe
 
PDF
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
Justin Lin
 
PPT
JS2
Jiang Wu
 
PDF
潜力无限的编程语言Javascript
jay li
 
PDF
Ecmascript
jay li
 
PPTX
Js的国(转载)
Leo Hui
 
PDF
JavaScript现代化排错实践
jeffz
 
改善程序设计技术的50个有效做法
crasysatan
 
About closure
otakustay
 
泛型总结
wang hongjiang
 
The Evolution of Async Programming (GZ TechParty C#)
jeffz
 
functional-scala
wang hongjiang
 
Hello Javascript
Baidu, Inc.
 
前端测试
frontwindysky
 
Scala function-and-closures
wang hongjiang
 
Javascript share
Xu Mac
 
jQuery源码学习
fangdeng
 
Wind.js无障碍调试与排错
jeffz
 
Js对象及函数式编程乱步
Pierre Woo
 
Jni攻略之八――操作对象的构造方法
yiditushe
 
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
Justin Lin
 
潜力无限的编程语言Javascript
jay li
 
Ecmascript
jay li
 
Js的国(转载)
Leo Hui
 
JavaScript现代化排错实践
jeffz
 

Viewers also liked (14)

PPTX
Tutorial bergabung
Ajhie Soeryo
 
PPTX
Tutorial bergabung jeunesse
Ajhie Soeryo
 
PPTX
ACRONYMS OF BROADCAST MEDIA
m_isbah
 
PDF
Java script closures
skywalker1114
 
PDF
Untitled presentation
Andrew Brewer
 
PPTX
Presentasi
Ajhie Soeryo
 
PPTX
Teresa Crash Assignment
Teresa Lai
 
PDF
Skin clinic Mumbai
Cosderma
 
PPTX
Connect & combine
eoherlihy
 
PPTX
Creativity Assignment 2
eoherlihy
 
PPT
Muhammed Roobas Oliyath's Profile
Roobas Oliyath
 
PPTX
Hyaluronic acid anti-ageing syrum
Cosderma
 
PPTX
Newderma skin clinic Mira road
Cosderma
 
PDF
cosderma chemical peels
Cosderma
 
Tutorial bergabung
Ajhie Soeryo
 
Tutorial bergabung jeunesse
Ajhie Soeryo
 
ACRONYMS OF BROADCAST MEDIA
m_isbah
 
Java script closures
skywalker1114
 
Untitled presentation
Andrew Brewer
 
Presentasi
Ajhie Soeryo
 
Teresa Crash Assignment
Teresa Lai
 
Skin clinic Mumbai
Cosderma
 
Connect & combine
eoherlihy
 
Creativity Assignment 2
eoherlihy
 
Muhammed Roobas Oliyath's Profile
Roobas Oliyath
 
Hyaluronic acid anti-ageing syrum
Cosderma
 
Newderma skin clinic Mira road
Cosderma
 
cosderma chemical peels
Cosderma
 
Ad

Similar to Java script closures (16)

PPT
Javascript Training
beijing.josh
 
PPTX
JavaScript closures
Horky Chen
 
PPT
揭开Javascript的面纱
qiang
 
PPT
Java Script 引擎技术
bigqiang zou
 
PDF
Javascript 闭包
jason hu 金良胡
 
PDF
Javascript primer plus
Dongxu Yao
 
PPT
Javascript之昨是今非
Tony Deng
 
PDF
Js is js(程劭非) (1)
looneyren
 
PPTX
Ecma script3
gniavaj
 
PPT
面向对象的Js培训
yiditushe
 
PPTX
追风堂 Javascript
minipeach
 
PPTX
JavaScript 闭包分享(一):传递参数
Janlay Wu
 
PDF
Javascript进阶编程
iflytek
 
PPT
Underscore
cazhfe
 
PPT
Javascript OOP
凯 高
 
PPT
Js培训
yiditushe
 
Javascript Training
beijing.josh
 
JavaScript closures
Horky Chen
 
揭开Javascript的面纱
qiang
 
Java Script 引擎技术
bigqiang zou
 
Javascript 闭包
jason hu 金良胡
 
Javascript primer plus
Dongxu Yao
 
Javascript之昨是今非
Tony Deng
 
Js is js(程劭非) (1)
looneyren
 
Ecma script3
gniavaj
 
面向对象的Js培训
yiditushe
 
追风堂 Javascript
minipeach
 
JavaScript 闭包分享(一):传递参数
Janlay Wu
 
Javascript进阶编程
iflytek
 
Underscore
cazhfe
 
Javascript OOP
凯 高
 
Js培训
yiditushe
 
Ad

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