JavaScript--闭包(closure)理解

来源:互联网 发布:iphone蓝牙传输软件 编辑:程序博客网 时间:2024/06/07 10:19

JavaScript–闭包理解

学习JavaScript,肯定会接触到闭包。
如果是刚接触js的,往往难以清楚理解。

闭包是什么

函数对象通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这特性在计算机科学文献中就被称为“闭包

从技术角度看,所有js函数都是闭包:它们都是对象,都关联到作用域链。定义大多数函数的作用域链在调用函数时依然有效,但这不影响闭包。

看一个嵌套函数:

var scope="global";//全局变量function checkscope(){    var scope="local";//局部变量    function f(){return scope;}//在作用域中返回该值    return f;}checkscope()();//local

代码中的f函数,就是闭包。
我的理解:闭包就是能够读取其他函数内部变量的函数。

在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

讲一个例子:

function buildList(list) {    var result = [];    for (var i = 0; i < list.length; i++) {        var item = 'item' + i;        result.push( function() {console.log(item + ' ' + list[i])} );        //push进去的是不是三个函数的定义,只有在你调用函数的时候去运行的时候,编译器才会去查看这个i的值到底是什么,而最后i肯定是length,如果要实现我们目的在push定义的变量时顺便把i的值给绑死        console.log(22);    }    return result;}function testList() {    var fnlist = buildList([1,2,3]);//执行这步时就回输出”22“3次了    // Using j only to help prevent confusion -- could use i.    for (var j = 0; j < fnlist.length; j++) {        fnlist[j]();    }} testList(); /logs "22" 3 times //logs "item2 undefined" 3 times //所以循环已经完成了 修改方法: push进去的是已经执行的函数的结果状态,而不是未执行定义的方法(容易理解一点吧)  result.push( (function() {console.log(item + ' ' + list[i])})() );  =  var p=function() {console.log(item + ' ' + list[i])};  result.push(p());然后修改调用为:  fnlist[j];

闭包可以捕捉局部变量(和参数)并保存


闭包特点及用途

特点

  • 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  • 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

用途

  • 读取函数内部的变量

  • 保持变量的值始终在内存中,保护数据

使用闭包做计数器

function counter(){    var n=0;    return {        count:function(){return n++;},        reset:function(){n=0;}        };}var a=counter(),d=counter();c.count();//0d.count();//0   两者互不影响c.count();//1   

用闭包模拟私有方法

如何使用闭包来定义公共函数,且其可以访问私有函数和变量—- 模块模式(module pattern):

var makeCounter = function() {  var privateCounter = 0;  function changeBy(val) {    privateCounter += val;  }  return {    increment: function() {      changeBy(1);    },    decrement: function() {      changeBy(-1);    },    value: function() {      return privateCounter;    }  }  };var Counter1 = makeCounter();var Counter2 = makeCounter();console.log(Counter1.value()); /* logs 0 */Counter1.increment();Counter1.increment();console.log(Counter1.value()); /* logs 2 */Counter1.decrement();console.log(Counter1.value()); /* logs 1 */console.log(Counter2.value()); /* logs 0 */

闭包的常见写法

1.对象赋值调用写法

var a= new Object();  a.pow= function(r) {         return  r * r;  };consol.log(a.pow(1.0));

2.声明对象调用写法

var a={      pow: function(r){               return  r * r;          }  };  console.log(a.pow(1.0))

3.匿名函数调用写法

(function(r){          var pow=r * r;          console.log(pow);              }  )(1.0);

4.函数返回值写法

function a(r){    function pow(){        return  r * r;    }    return area();}console.log(a(1.0));

5.原型调用写法

function a(r) {      this.r = r;  }  a.prototype.pow= function() {      return  this.r * this.r;  }var c = new a(1.0);     console.log(c.pow()); 
0 0