JavaScript闭包使用方法详解

闭包就是一种在函数内访问和操作外部变量的方式,一般情况下,我们会在函数外部定义一些变量以供函数内部使用。

 代码如下 复制代码
var a = 1;
function fn( arg ){
 var b =2;
 function fnInner ( arg ){
 console.log(a); //访问全局的变量
 console.log(b); //访问外部函数体内的变量
 console.log(arg); //访问函数自身的变量
 }
 fnInner(3);
}

fn函数的闭包引用了变量b,还有函数本身。fnInner函数引用了b,a,传递给它的参数。我们需要注意一点,虽然函数并没有特别创建一个变量来保存这些要引用的数据,但是要保存和引用这些变量还是会带来内存的消耗。

私有变量
JavaScript语言本身并没有提供创建私有变量的方式,但是我们知道,函数外的变量是无法访问函数内部的变量的,这意味着我们可以这样创建私有变量:

 代码如下 复制代码
function(){
 this.public = 1; //public在函数外面可以访问
 var private = 1;//private变量在函数外部无法访问
}

回调函数和定时器
有时候我们会这样写一个回调函数

 代码如下 复制代码
var a = 1;
jQuery.ajax({
 url : "test.html",
 success : function(html){
 console.log(a);
 }
})

类似的的还有在设置定时器的时候,我们在1000ms后将一个函数插入队列等待执行

 代码如下 复制代码
var a = 1;
setTimeout(function(){
 console.log(a);
},1000);
a = a + 1;

ajax回调里的结果可能比较容易猜到,匿名函数本身是一个闭包,保存了变量a的值,从而可以访问。而第二个定时器回调主要要说明的就是,闭包所引用的值是在执行期生成的,而我们虽然在a = a+1前面定义了匿名函数,但是执行的时候因为匿名函数被插入到执行队列的尾部,那么a = a +1会先执行,然后在执行匿名函数,也就是说这个例子返回的值为2。
改变闭包的context
有这么一段代码

 代码如下 复制代码
var Button = {
  click: function(){
    console.log(this);
    this.clicked = true;
  }
};
var elem = document.querySelector("body");
elem.addEventListener("click", Button.click, false);

我们的目的是通过点击body来改变Button对象的clicked值,但是失败了

虽然我们在定义的时候试图让this指向了Button,但是在addEventListener之后,this又被指向到elem。

解决方法有很多。

在支持Function.prototype.bind方法的浏览器里,我们只需要简单地修改一下代码即可

 代码如下 复制代码
var Button = {
  click: function(){
    console.log(this);
    this.clicked = true;
  }
};
var elem = document.querySelector("body");
elem.addEventListener("click", Button.click.bind(Button), false);

注:Function.prototype.bind方法参考ECMAScript 262 15.3.4.5中的说明,作用和apply类似,但是不会执行原函数

如果不支持Function.prototype.bind,那么,我们可以自己实现一个bind函数。

 代码如下 复制代码
function bind(context, name){
  return function(){
    return context[name].apply(context, arguments);
  };
}
var Button = {
  click: function(){
    console.log(this);
    this.clicked = true;
  }
};
var elem = document.querySelector("body");
elem.addEventListener("click", bind(Button, "click"), false);

本文参考自John Resign的《secrets of the JavaScript ninjia》

时间: 2024-10-24 23:32:27

JavaScript闭包使用方法详解的相关文章

javaScript数组迭代方法详解_javascript技巧

本文为大家介绍了javaScript数组迭代方法,供大家参考,具体内容如下 每个方法都接收两个参数:要在每一项上运行的函数  和  (可选的)运行该函数的作用域对象. 传入这些方法中的函数会接收三个参数:数组项的值,该项在数组中的位置,数组对象本身. forEach()  对数组中的每一项运行 给定函数.该方法没有返回值.every()  对数组中的每一项运行 给定函数,如果数组的每一项都返回true,则返回true.some()  对数组中的每一项运行 给定函数,如果数组的任意一项返回true

JavaScript中借用方法详解

通过call().apply()和bind()方法,我们可轻易地借用其它对象的方法,而无须从这些对象中继承它. 在JavaScript中借用方法 在JavaScript中,有时可以重用其它对象的函数或方法,而不一定非得是对象本身或原型上定义的.通过 call().apply() 和 bind() 方法,我们可轻易地借用其它对象的方法,而无须继承这些对象.这是专业 JavaScript 开发者常用的手段. 前提 本文假设你已经掌握使用 call().apply() 和 bind() 的相关知识和它

Javascript解析URL方法详解_javascript技巧

URL : 统一资源定位符 (Uniform Resource Locator, URL) 完整的URL由这几个部分构成: scheme://host:port/path?query#fragment scheme  = 通信协议 (常用的http,ftp,maito等) host = 主机 (域名或IP) port = 端口号 path = 路径 query = 查询 可选,用于给动态网页(如使用CGI.ISAPI.PHP/JSP/ASP/ASP.NET等技术制作的网页)传递参数,可有多个参数

javascript字符串连接方法详解(性能测试)

js的字符串连接有两种:用"+"连接:用array的join连接.  代码如下 复制代码 var a1=10; var a2=20; a3 = a1 + a2 //数字加数字 alert(typeof(a3)) //number alert("a1+a2="+a3) //a1+a2= 30 alert(typeof("a1+a2="+a3)) //字符串"a1+a2"加数字a3;得到的是字符串,输出string alert(&

javascript字符串拼接方法详解

字符串拼接在JS中是常遇到的,有时候遇到长字符串的拼接就会比较麻烦了.比如html字符串:  代码如下 复制代码 var str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; var str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 编辑器的宽度有限,为了程度的可读性,必须对字符串

javascript 正则表达式定义方法详解

javascript中使用正则表达式有两种方式.第一种是构建一个RegExp对象:第二种是使用"//"来定义,也即perl风格.例如:  代码如下 复制代码 var str = 'http://www.111cn.net/'; var reg = new RegExp('http', 'i'); alert(reg.test(str)); 或 alert(/http/.test(str)); 上述例子就是使用两种方式判断字符串str中是否包含http,注意第二种方式 // 一定不能使用

Javascript获取图片原始宽度和高度的方法详解_javascript技巧

前言 网上关于利用Javascript获取图片原始宽度和高度的方法有很多,本文将再次给大家谈谈这个问题,或许会对一些人能有所帮助. 方法详解 页面中的img元素,想要获取它的原始尺寸,以宽度为例,可能首先想到的是元素的innerWidth属性,或者jQuery中的width()方法. 如下: <img id="img" src="1.jpg"> <script type="text/javascript"> var img

JavaScript原生对象之Date对象的属性和方法详解

 这篇文章主要介绍了JavaScript原生对象之Date对象的属性和方法详解,需要的朋友可以参考下     创建 Date 对象的语法: 代码如下: //Date 对象会自动把当前日期和时间保存为其初始值. new Date();   //value-毫秒:代表自世界协调时1970年1月1日00:00:00开始的数值. new Date(value); //dateString-日期字符串:表示日期的字符串值.此字符串应该是在parse方法中识别的格式. new Date(dateString

JavaScript原生对象之Number对象的属性和方法详解

 这篇文章主要介绍了JavaScript原生对象之Number对象的属性和方法详解,本文讲解了创建 Number 对象的语法.MAX_VALUE.MIN_VALUE.NaN等属性或方法,需要的朋友可以参考下     创建 Number 对象的语法: 代码如下: var myNum = new Number(value); var myNum = Number(value); 当 Number() 和运算符 new 一起作为构造函数使用时,它返回一个新创建的 Number 对象.如果不用 new