通过示例彻底搞懂js闭包

例1

function sayHello(name)
{
 var text = 'Hello ' + name;
 var sayAlert = function() { console.log(text); }
 sayAlert();
}

sayHello("Bob") // 输出"Hello Bob"

在sayHello()函数中定义并调用了sayAlert()函数;sayAlert()作为内层函数,可以访问外层函数sayHello()中的text变量。

例2

function sayHello2(name)
{
 var text = 'Hello ' + name; // 局部变量
 var sayAlert = function() { console.log(text); }
 return sayAlert;
}

var say2 = sayHello2("Jane");
say2(); // 输出"Hello Jane"

例3

function buildList(list) {
 var result = [];
 for(var i = 0; i < list.length; i++) {
  var item = 'item' + list[i];
  result.push(
    function() {
      console.log(item + ' ' + list[i]);
    }
   );
 }
 return result;
}

var fnlist = buildList([1,2,3]);
for (var j = 0; j < fnlist.length; j++) {
  fnlist[j]();
}

得到的结果:连续输出3个"item3 undefined"

解析:通过执行buildList函数,返回了一个result,那么这个result存放的是3个匿名函数。然而这三个匿名函数其实就是三个闭包,因为它可以访问到父函数的局部变量。所以闭包内的保留的i是最终的值为3.所以list[3]肯定是undefined. item变量值为item3.

改成如下代码:

function buildList(list) {
 var result = [];
 for(var i = 0; i < list.length; i++) {
  var item = 'item' + list[i];
  result.push(
    (function(i) {
      console.log(item + ' ' + list[i]);
    })(i)
   );
 }
 return result;
}

var fnlist = buildList([1,2,3]);

得到的结果:

item1 1
item2 2
item3 3

解释:这儿虽然传递了一个数组进去,但是返回的是三个自执行的函数。

例4

function newClosure(someNum, someRef)
{
 var anArray = [1,2,3];
 var num = someNum;
 var ref = someRef;
 return function(x)
 {
 num += x;
 anArray.push(num);
 console.log('num: ' + num + "; " + 'anArray ' + anArray.toString() + "; " + 'ref.someVar ' + ref.someVar);
 }
}
closure1 = newClosure(40, {someVar: "closure 1"});
closure2 = newClosure(1000, {someVar: "closure 2"});
closure1(5); // 打印"num: 45; anArray 1,2,3,45; ref.someVar closure 1"
closure2(-10); // 打印"num: 990; anArray 1,2,3,990; ref.someVar closure 2"

每次调用newClosure()都会创建独立的闭包,它们的局部变量num与ref的值并不相同。

例5

function sayAlice()
{
 var sayAlert = function() { console.log(alice); }
 var alice = 'Hello Alice';
 return sayAlert;
}

var sayAlice2 = sayAlice();
sayAlice2(); // 输出"Hello Alice"

alice变量在sayAlert函数之后定义,这并未影响代码执行。因为返回函数sayAlice2所指向的闭包会包含sayAlice()函数中的所有局部变量,这自然包括了alice变量,因此可以正常打印”Hello Alice”。

例6

function setupSomeGlobals() {
 var num = 666;
 gAlertNumber = function() { console.log(num); }
 gIncreaseNumber = function() { num++; }
 gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
gAlertNumber(); // 输出666
gIncreaseNumber();
gAlertNumber(); // 输出667
gSetNumber(5);
gAlertNumber(); // 输出5

解释:首先gAlertNumber,gIncreaseNumber,gSetNumber是三个全局变量,并且其三个值都是匿名函数,然而这三个匿名函数本身都是闭包。他们操作的num都是保存在内存中的同一个num,所有会得出上面的结果。

以上这篇通过示例彻底搞懂js闭包就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 理解javascript中的闭包

    阅读目录 什么是闭包? 闭包的特性 闭包的作用: 闭包的代码示例 注意事项 总结 闭包在javascript来说是比较重要的概念,平时工作中也是用的比较多的一项技术.下来对其进行一个小小的总结 什么是闭包? 官方说法: 闭包是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量------<javascript高级程序设计第三版> 下面就是一个简单的闭包: function A(){ var text="

  • 详谈JavaScript的闭包及应用

    闭包真的是学过一遍又一遍,Js博大精深,每次学习都感觉有新的收获.相信在大家封装前端插件时,闭包是必不可少的.闭包的真正好处我个人认为除了封装还是封装,能带个我们私有方法,和调用上的灵活方便,也会使你的代码对外的对象保持干净整洁. 进入正题 维基百科这样定义了JS闭包:在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的

  • 浅谈JS封闭函数、闭包、内置对象

    一.变量作用域指的是变量的作用范围,javascript中的变量分为全局变量和局部变量 1.全局变量:在函数之外定义的变量,为整个页面公用,函数的内部外部都可以访问. 2.局部变量:在函数内部定义的变量,只能在定义该变量的函数内部访问,外部无法访问.函数内部访问变量时,先在内部查找是否有此变量,如果有,就使用内部,如果没有,就去外部查找 二.封闭函数封闭函数是javascript中匿名函数的另外一种写法,创建一个一开始就执行而不用命名的函数. 1.一般函数的定义和执行函数 2.封闭函数的定义和执

  • JavaScript闭包和回调详解

    一.闭包 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包有三个特性: 1.函数嵌套函数; 2.函数内部可以引用外部的参数和变量; 3.参数和变量不会被垃圾回收机制回收. 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量.使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量.全局变量在每个模块都可调用,这势必将是

  • 浅谈javascript的闭包

    关于闭包的解释 我们将作用域链描述为一个对象列表,不是绑定的栈.每次调用javascript函数的时候,都会为之创建一个新的对象来保存变量,把这个对象添那个加至作用域中,当函数返回时,就从作用域链中将这个绑定变量的对象删除,如果不存在嵌套函数,也没有其他引用指向这个绑定的对象,它就会被当垃圾回收掉, (function () { var val = null; var callback; setTimeout(function () { val = 1; callback(val) },1000

  • 轻松学习Javascript闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 当function里嵌套function时,内部的function可以访问外部function里的变量. function foo(x) { var tmp = 3; function bar(y) { alert(x + y + (++tmp)); } bar(10); } foo(2) 不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp. 但

  • 轻松理解JavaScript闭包

    摘要 闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包 一.什么是闭包? 闭包就是可以访问另一个函数作用域中变量的函数. 下面列举出常见的闭包实现方式,以例子讲解闭包概念 function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000 f1

  • 深入理解Javascript中的作用域链和闭包

    首先我们回顾下之前一篇关于介绍数组遍历的文章: 请先看上一篇中提到的for循环代码: var array = []; array.length = 10000000;//(一千万) for(var i=0,length=array.length;i<length;i++){ array[i] = 'hi'; } var t1 = +new Date(); for(var i=0,length=array.length;i<length;i++){ } var t2 = +new Date();

  • JavaScript中闭包的详解

    闭包是什么 在 JavaScript 中,闭包是一个让人很难弄懂的概念.ECMAScript 中给闭包的定义是:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量. 是不是看完这个定义感觉更加懵逼了?别急,我们来分析一下. 闭包是一个函数 闭包可以使用在它外面定义的变量 闭包存在定义该变量的作用域中 好像有点清晰了,但是使用在它外面定义的变量是什么意思,我们先来看看变量作用域. 变量作用域 变量可分为全局变量和局部变量.全局变量的作用域就是全局性的,在 js

  • JS闭包用法实例分析

    本文实例讲述了JS闭包用法.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> // 第一,函数作为返回值 function fn(){ var m

随机推荐