常见面试题JavaScript闭包(ES5语法)

iefreer 发表于 2017-01-02 23:05:17

标签: javascript, closure, 基础知识, 常见面试题

- +

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。

你可以自己在线试试看

possitive(0) negative(0) views2139 comments1
私信 收藏 分享
分享到

发送私信

最新评论

iefreer 2017-01-02 23:08:28

参阅DC的经典文章:http://www.crockford.com/javascript/private.html


请先 登录 再评论.
相关文章
  • 创建非矩形网页页面元素的常用技术和实例代码

    非矩形设计正在变成一种时尚,比如波浪形、菱形、三角形等:而随着技术发展,这种设计在技术实现上也变得更容易。本文以最简单的三角形为例,演示使用5种方法来...

  • 使用HTML5 FileReader和Canvas压缩用户上传的图片

    手机用户拍的照片通常会有2M以上,这对服务器带宽产生较大压力。因此在某些应用下(对图片要求不那么高)我们可以在客户端来压缩图片,然后再提交给服务器。总体...

  • WebVR简介和常用资源链接

    什么是WebVR这是一个实验性的JavaScript API,提供了在用户网页浏览器中访问虚拟现实设备的统一接口。当前主流VR设备如Oculus Rift DK2、谷歌的CardBoard、三星...

  • Three.js入门教程5 - 10个必须知道的编程技巧

    作者为Google的Paul,关于如何写出好的WebGL代码的文章。和很多开发者一样,我通过实践学习,但同时我也向其他更有经验的开发者们学习。在过去的几个月中,我在c...

  • Three.js入门教程4 - 创建粒子系统动画

    嗨,又见面了。这么说我们已经开始学习Three.js了,如果你还没有看过之前三篇教程,建议你先读完。如果你已经读完前面的教程了,你可能会想做一些关于粒子的东西。让我们直面这个话题吧,每个人都爱粒子效果。不管你是否知道,你可以很轻易地创建它们。

  • WebGL入门教程5 - 详解纹理滤镜(Texture Filter)

    WebGL中使用纹理贴图来实现细腻的物体表面观感,其中一个重要的参数是纹理滤镜(Texture Filter)。
    这个参数用来处理当对象出现缩放时,纹理如何处理中间...

  • WebGL入门教程4 - 使用纹理贴图(Texture Map)

    3D建模和纹理贴图的关系就好比人体和皮肤(或着装)的关系,3D建模用来处理空间属性,而贴图适合用来处理细腻的表面属性。如果不使用贴图,而想在表面达到足够的...

  • 如何使用WebGL创建一个逼真的下雨动画

    之前写过文章来分别讲解如何使用CSS3和Canvas2D实现过雨滴和下雨动画。通过背景处理看起来也有视觉上的3D效果,但并非真正的3D场景,如果要加入用户交互,进行36...

  • 如何基于Canvas来模拟真实雨景Part2:重力掉落和雨滴融合

  • 如何使用纯CSS3实现一个3D泡沫

    要实现一个逼真的泡沫,涉及到比较复杂的光学/物理学知识。我们这里先简化下问题,实现一个相对简单而足够实用的泡沫元素。我们可以把基础的泡沫元素应用在很多场景中,比如水景、泡咖啡、啤酒甚至火焰特效中。泡沫首先是一个圆形元素.bubble

  • 如何使用CSS3/SCSS实现逼真的车窗雨滴效果

    在天气预报类的Web移动应用中,常常需要实现屏幕的雨滴效果,表示阴雨天气。感觉上比较神奇,其实想通了,这个效果的实现只需要一点物理知识和CSS3的简单变换。实现一个小雨滴首先雨滴是一个个小的椭圆形元素:.raindrop

  • 在PHP网页程序中执行Sass/Compass命令

    我们需要在wow云开发平台支持sass/compass等预编译样式语言,为此我们首先尝试了scssphp扩展,但是在支持最新语法上,经常会出现异常。所以我们采用了代理的方式...

  • 更多...