javascript 闭包

简介:
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://dba10g.blog.51cto.com/764602/1357820

目录

定义

引子

闭包的用途

一个常见错误

 

 

 


定义

闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境

引子

首先看一个例子

1
2
3
4
5
6
7
8
9
function  makeFunc() {
var  name =  "Mozilla" ;
function  displayName() {
alert(name);
}
return  displayName;
}
var  myFunc = makeFunc();
myFunc();

这段代码看起来别扭却能正常运行。通常,函数中的局部变量仅在函数的执行期间可用。一旦 makeFunc() 执行过后,我们会很合理的认为 name 变量将不再可用。不过,既然代码运行的没问题,显然不是我们想象的那样。在我们的例子中,myFunc 是一个闭包,由 displayName 函数和闭包创建时存在的 "Mozilla" 字符串形成。

这就是闭包,我们在返回函数的时候,也将函数的环境一并返回了。

闭包的用途

  1. 响应事件而执行的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< html >
< head >
< script  type = "text/javascript" >
function makeSizer(size){
return function(){
document.body.style.fontSize=size+"px";
}
}
var size12= makeSizer(12);
var size14= makeSizer(14);
var size16= makeSizer(16);
window.onload=function(){
document.getElementById("a12").onclick=size12;
document.getElementById("a14").onclick=size14;
document.getElementById("a16"). name="a12" id="a12">12</ a >
< a  name = "a12"  id = "a14" >14</ a >
< a  name = "a12"  id = "a16" >16</ a >
</ body >
</ html >

 2.  模拟似有方法

诸如 Java 在内的一些语言支持将方法声明为私有的,既它们只能被同一个类中的其它方法所调用。

对此,JavaScript 并不提供原生的支持,但是可以使用闭包模拟私有方法。私有方法不仅仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱了代码的公共接口部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script type= "text/javascript" >
function  MyObject(){
var  name= "" ;
return  {
getName: function (){
return  name;
},
setName: function (str){
name=str;
}
}
}
var  mo = MyObject();
mo.setName( "Mo1" );
alert(mo.getName()); //Mo1
alert(mo.name); //undefined
</script>

在上面的例子中,name作为私有属性,getName,setName为公有方法。

 

一个常见的错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
< html >
< head >
</ head >
< body >
< p  id = "help" >Helpful notes will appear here</ p >
< p >E-mail: < input  type = "text"  id = "email"  name = "email" ></ p >
< p >Name: < input  type = "text"  id = "name"  name = "name" ></ p >
< p >Age: < input  type = "text"  id = "age"  name = "age" ></ p >
< script  type = "text/javascript" >
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i <  helpText.length ; i++) {
var  item  helpText [i];
document.getElementById(item.id) .onfocus  function () {
showHelp(item.help);//item.help 为最后一个对象的help
}
}
}
setupHelp();
</script>
</ body >
</ html >

该问题的原因在于赋给 onfocus 的函数是闭包;它们由函数定义和记录自 setupHelp 函数作用域的环境构成。一共创建了三个闭包,但是它们都共享同一个环境。在 onfocus 的回调被执行时,循环早已经完成,且此时 item 变量(由所有三个闭包所共享)已经指向了 helpText 列表中的最后一项。

 

修正

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
< html >
< head >
</ head >
< body >
< p  id = "help" >Helpful notes will appear here</ p >
< p >E-mail: < input  type = "text"  id = "email"  name = "email" ></ p >
< p >Name: < input  type = "text"  id = "name"  name = "name" ></ p >
< p >Age: < input  type = "text"  id = "age"  name = "age" ></ p >
< script  type = "text/javascript" >
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function makeHelpCallback(help){
return function(){
showHelp(help);
}
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i <  helpText.length ; i++) {
var  item  helpText [i];
document.getElementById(item.id) .onfocus  = makeHelpCallback (item.help);
}
}
setupHelp();
</script>
</ body >
</ html >

这段代码可以如我们所期望的那样工作。所有的回调不再共享同一个环境, makeHelpCallback 函数为每一个回调创建一个新的环境。在这些环境中,help 指向 helpText 数组中对应的字符串。

 

参考:https://developer.mozilla.org/zh-CN/docs/JavaScript/Guide/Closures

 

 

 

本文出自 “简单” 博客,请务必保留此出处http://dba10g.blog.51cto.com/764602/1357820

目录
相关文章
|
17天前
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理与实战
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理与实战
|
2天前
|
JavaScript 前端开发
js 闭包的优点和缺点
【10月更文挑战第27天】JavaScript闭包是一把双刃剑,在合理使用的情况下,它可以带来很多好处,如实现数据封装、记忆功能和模块化等;但如果不注意其缺点,如内存泄漏、变量共享和性能开销等问题,可能会导致代码出现难以调试的错误和性能问题。因此,在使用闭包时,需要谨慎权衡其优缺点,根据具体的应用场景合理地运用闭包。
89 58
|
2天前
|
缓存 JavaScript 前端开发
js 闭包
【10月更文挑战第27天】JavaScript闭包是一种强大的特性,它可以用于实现数据隐藏、记忆和缓存等功能,但在使用时也需要注意内存泄漏和变量共享等问题,以确保代码的质量和性能。
15 7
|
4天前
|
自然语言处理 JavaScript 前端开发
JavaScript闭包:解锁编程潜能,释放你的创造力
【10月更文挑战第25天】本文深入探讨了JavaScript中的闭包,包括其基本概念、创建方法和实践应用。闭包允许函数访问其定义时的作用域链,常用于数据封装、函数柯里化和模块化编程。文章还提供了闭包的最佳实践,帮助读者更好地理解和使用这一强大特性。
10 2
|
20天前
|
设计模式 JavaScript 前端开发
探索JavaScript中的闭包:从基础概念到实际应用
在本文中,我们将深入探讨JavaScript中的一个重要概念——闭包。闭包是一种强大的编程工具,它允许函数记住并访问其所在作用域的变量,即使该函数在其作用域之外被调用。通过详细解析闭包的定义、创建方法以及实际应用场景,本文旨在帮助读者不仅理解闭包的理论概念,还能在实际开发中灵活运用这一技巧。
|
21天前
|
缓存 JavaScript 前端开发
深入了解JavaScript的闭包:概念与应用
【10月更文挑战第8天】深入了解JavaScript的闭包:概念与应用
|
1月前
|
自然语言处理 JavaScript 前端开发
Javascript中的闭包encloure
【10月更文挑战第1天】闭包是 JavaScript 中一种重要的概念,指函数能够访问其定义时的作用域内的变量,即使该函数在其词法作用域之外执行。闭包由函数及其词法环境组成。作用域链和词法作用域是闭包的核心原理。闭包常用于数据隐藏和封装,如模块模式;在异步操作中也广泛应用,如定时器和事件处理。然而,闭包也可能导致内存泄漏和变量共享问题,需谨慎使用。
|
17天前
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理、应用与代码演示
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理、应用与代码演示
|
18天前
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript闭包:原理与应用
【10月更文挑战第11天】深入理解JavaScript闭包:原理与应用
14 0
|
2月前
|
JSON JavaScript 前端开发
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级