常见面试题JavaScript闭包(ES5语法)
JavaScript闭包(Closure)是常见的JS面试题,是否理解闭包是一个简单的区分JS初级和高级程序员的判例。
几乎每个JS程序员都在使用闭包,有意或无意间。比如编写一个jQuery鼠标点击处理函数:
$(function() { var option; $(".scssbox").click(function() { // 闭包,该闭包同时也是一个匿名函数 option = scss; // 闭包可以访问和改变其外部函数(包含函数)中的变量 }); }
什么是闭包
“闭包”实际上就是一个函数,该函数被定义在一个包容(外部)函数的内部,并能够访问外部函数的变量,即使外部函数已返回。
这种外部变量访问能力不是通过数值拷贝传递,而是通过引用(Reference)传递的,因此闭包可以读取并改变外部变量的取值。
function Name (firstName, lastName) { var nameIntro = "Your name is "; // 该内部函数能访问外部函数中定义的变量,以及参数 function makeFullName () { return nameIntro + firstName + " " + lastName; } return makeFullName (); } console.log( Name("Michael", "Jordan") ); // Your name is Michael Jordan
注意:上述代码中的闭包不能被公开函数(public function)所调用,另外闭包不能访问外部函数的arguments变量。所谓公开函数指的是通过原型(prototype)扩展来定义的对象函数。
为什么需要闭包
闭包的好处是可以方便的完成外部函数对象的某些特定功能。
我们可以类比C++等其他面向对象的语言,访问控制是面向对象语言的一个基本特征,
而通过闭包,我们可以在JS语言中实现对象私有成员函数(private member function)和授权函数的功能。
闭包的陷阱
由于闭包能够修改外部函数变量,如果不小心,可能会产生一些比较隐蔽的问题:
function Member(users) { var i; var uniqueID = 100; for (i = 0; i < users.length; i++) { users[i]["id"] = function() { return uniqueID + i; } } return users; } var users = [{ name: "Ryan", id: 0 }, { name: "Mike", id: 0 }, { name: "Mark", id: 0 }]; var members = Member(users); var rid = members[0]; console.log(rid.id()); // 103
上面的代码本来是想给3个用户分别分配唯一成员编号100、101、102,但实际上都是103。
原因就是在调用Member函数并返回后,i已经被修改为3,那么当再次调用闭包函数获取唯一编号时就已经是103。
你可以自己在线试试看。
- 相关文章
增强现实引擎ARToolKit工作原理简介
ARToolkit是一个基于CV(计算机视觉)和Marker(标识)的开源增强现实引擎。其具备如下功能特性:A. 鲁棒跟踪,包括基于标记的跟踪与基于特征的跟踪;
A-Frame WebVR(网页虚拟现实)快速开发入门教程
WebVR和WebGL应用程序接口使得我们已经可以在浏览器上创建虚拟现实(VR)体验,但从工程化的角度而言,开发社区还需要更多方便强大的开发库来简化编程,Mozilla的
CSS3人行走动作图解和动画实现
对于人类而言,行走是一种很自然的想要前进并防止跌倒的一组动作重复。大部分人1岁就学会了走路,但至此以后的几十年间,或许我们从来没留意过自己行走姿势。当...
JavaScript事件模型图解
在JavaScript中用户交互的核心部分就是事件处理。本文为对事件模型和处理机制的总体性描述。Event是什么?
event是用户操作网页时发生的交互动作,比如clic...使用CSS3 box-decoration-break特性实现多行文本样式
当文章中的长文本被自动断行为多行文本时,其样式可能会出乎我们的设计。本文介绍如何使用CSS3中的box-decoration-break特性来处理多行元素样式。
按照规范...HTTP1.1协议现状、问题和解决方案
HTTP的现状最早的HTTP协议非常简单,只能用来传送文本,方法也只有GET,后来逐步发展到1.1,能够支持多种MIME格式数据(如文本、文件),支持GET,POST,HEAD,OPTI...
如何使用Three.js加载obj和mtl文件
OBJ和MTL是3D模型的几何模型文件和材料文件。在最新的three.js版本(r78)中,以前的OBJMTLLoader类已废弃。现在要加载OBJ和MTL文件,需要结合OBJLoader和MTLLoade...
浏览器控制台报JS脚本执行错误:Module is not defined
现在JS分成了两个分支,一部分在服务器端发展如NodeJS,一部分是传统的浏览器运行环境。
有些插件在编写JS代码时,是针对Node编写的,所以直接在浏览器中使...WebGL入门教程3 - Canvas、Context、API和绘制一个矩形
如何基于Canvas来模拟真实雨景Part2:重力掉落和雨滴融合
如何基于Canvas来模拟真实雨景Part1:预备知识和创建基本对象
HTML网页布局:静态、自适应、流式、响应式
静态布局(Static Layout)即传统Web设计,对于PC设计一个Layout,在屏幕宽高有调整时,使用横向和竖向的滚动条来查阅被遮掩部分;对于移动设备,单独设计一个布...
Canvas实例教程:图像移动、大小调整和裁剪
本文介绍如何使用JavaScript和HTML5 Canvas元素来移动、调整大小和...
Processing.js和P5.js的功能简介和区别
什么是ProcessingProcessing是关于数字艺术的编程语言,支持跨平台,语言本身是一个类Java语言,程序文件的后缀为.pde。
什么是Processing.js为了能让Proce...使用CSS3实现流星雨动画教程
很多营销页面中需要实现类似流星雨的动画背景,营造节日浪漫的气氛。要实现这样的效果,有两种方法,一个是使用Canvas,一个是使用纯CSS3,我们这里介绍第2种方...
更多...