JavaScript之闭包(重新认识)

最近又重新学习了闭包,发现之前没有深刻理解作用域链,学习作用域链后对闭包才可以做到真正的理解。

      闭包是指有权另一个函数作用域中变量的函数。要理解闭包首先理解作用域链。

      执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有与之关联的变量对象,保存了环境中定义的所有变量和函数。只有解析器在处理数据是我才可以访问这个变量。当代码在一个环境中执行时,会创建变量对象的一个作用域链,它保证了执行环境对有权访问的变量和函数的有序访问。

当某个函数被调用时,会创建一个执行环境及相应的作用域链。作用域的最前端,始终都是当前执行代码所在环境的变量对象,下一个变量对象来自外部环境,以此类推,直到全局作用域中的变量对象作为作用域链的终点。作用域链中一定不会包含其内部子函数的变量对象,但子函数的作用域链包含函数的局部变量,因此这决定创建闭包的方法是在一个函数内部创建另一个函数,内部函数可以引用外部函数的变量。

闭包与变量

闭包只能取得函数中任何变量的最后一个值,如下创建一个数组函数

function creatFunction(){
  var result = new Array();
  for (var i=0; i<10; i++){
  result[i] = function(){
          return i;
   };
}
  return result;
}

表面上每个函数都会返回自己的索引,实际上都返回10。这是因为每个函数都引用作用域链中同一个变量i,当creatFunction()函数返回后,i的值是10。解决方法

(1) 创建匿名函数封装

function creatFunction(){
  var result = new Array();
  for (var i=0; i<10; i++){
  result[i] = function(num){
            function(){
                  return num;
         };
   }(i)
}
return result;
}

(2)使用ES6的let

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

function creatFunction(){
  var result = new Array();
  for (let i=0; i<10; i++){
         result[i] = function(){
             return i;
       };
  }
return result;
}

闭包特性

(1)封闭性:外界无法访问闭包内部的数据,如果在闭包内声明变量,外界是无法访问的,除非闭包主动向外界提供访问接口;

(2)持久性:一般的函数,调用完毕之后,局部活动对象就会被销毁,内存中仅保存全局作用域。而对于闭包来说,在外部函数被调用之后,闭包结构依然保存在。

闭包问题

(1) 占用内存。由于闭包携带包含它函数的作用域,因此会比其他函数占用更多内存。

(2) 引起内存泄漏。 闭包中引用HTML元素将无法被销毁。解决方法是将需要使用的DOM元素副本的属性保存在变量中,结束会销毁DOM元素。

时间: 2024-10-10 16:14:08

JavaScript之闭包(重新认识)的相关文章

javascript 关于闭包的知识点

javascript 关于闭包的认识 概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制. 所以要大致搞清三个东西:函数对象(function object).作用域链(scope chain)以及它们如何关联(combination) 首先要建立一个印象,在js中,几乎所有的东西可以看作对象,除了null和undefined.比如常用的数组对象.日期对象.正则对象等. var num = 123; // Number var arr = [1,2,3

javascript Closure 闭包

引用自 http://www.cnblogs.com/mguo/archive/2013/06/19/3143880.html /*一.变量的作用域要理解闭包,首先必须理解Javascript特殊的变量作用域.变量的作用域无非就是两种:全局变量和局部变量.Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量.*/ var n=999; function f1(){ alert(n); } f1(); // 999//另一方面,在函数外部自然无法读取函数内的局部变量. funct

JavaScript中闭包实现的私有属性的getter()和setter()方法

注意: 以下的输出都在浏览器的控制台中 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>闭包</title> </head> <body> <script type="text/javascript"> /** * 利用闭包实现 * 这个函数给对象o增加了属性存储器方法 * 方法名称为ge

javascript学习-闭包

javascript学习-闭包 1.什么是闭包 大多数书本中对闭包的定义是:“闭包是指有权访问另一个函数作用域中的变量的函数.”.这个概念过于抽象了,对初学者而言没啥帮助.好在<Javascript忍者秘籍>5.1中给了一个例子来进一步的解释了什么是闭包: var outerValue= 'ninja'; var later; function outerFunction() { var innerValue = "samurai"; function innerFunct

两个示例介绍JavaScript的闭包

JavaScript的闭包有两个用途:一个是访问函数内部的变量:另一个是让变量的值在作用域内保持不变.函数是JavaScript 中唯一有作用域的对象,因此JavaScript的闭包依赖于函数实现,下面结合两则示例对JavaScript的闭包做简单说明. 1. 访问函数内部的变量 JavaScript中没有严格意义上的类,所以我们常用函数来模拟类.我们可以像下面这样模拟一个Counter类,并在其中定义一个count私有变量: 在JavaScript中,函数可以访问其外部定义的变量,而外部不能访

JavaScript基础–闭包

JavaScript基础–闭包 理解闭包的概念对于学习JavaScript至关重要,很多新手(包括我)开始学习闭包时,都会感觉似懂非懂,之前看了一些资料,整理了闭包的一篇博客,若有疏忽与错误,希望大家多多给意见. 概述 理解闭包的概念前,建议大家先回想一下JS作用域的相关知识,如果有疑问的同学,可以参考:JavaScript基础–作用域.闭包的定义如下: Closure is when a function is able to remember and access its lexical s

javascript中闭包的工作原理

一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话通俗的来说就是:JavaScript中所有的function都是一个闭包.不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”.看下面这段代码: 1 2 3 4 5 6 7 function a() { var i = 0; function b() { ale

关于Javascript的闭包

要理解javascript的闭包 关键是弄明白三样事情 1.变量作用域 一言以蔽之  函数内部可以访问函数外部的字段  而反之不行 1 var n=999; 2 3 function f1(){ 4 alert(n); 5 } 6 7 f1(); // 999 1 function f1(){ 2 var n=999; 3 } 4 5 alert(n); // error 此处有一坑是 若在函数内声明变量不使用var关键字 相当于是声明全局变量 也就是window的变量 2.this的含义 th

javascript中闭包的原理与用法小结(转)

一.在javaScript中闭包的五种表现形式如下: 1 /** 2 * Created by admin on 2016/12/26. 3 *//* 4 //向函数对象添加属性 5 function Circle(r){ 6 this.r=r; 7 } 8 Circle.prototype.PI=3.1415926; 9 Circle.prototype.area=function(){ 10 return this.PI*this.r*this.r; 11 }; 12 var c=new C

深入理解JavaScript的闭包特性 如何给循环中的对象添加事件

初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript的闭包特性. 有个网友问了个问题,如下的html,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4. <!DOCTYPE HTML> <html> <head> <meta charset="utf-8" /> &