常见面试题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) views218 comments1
私信 收藏 分享
分享到

发送私信

最新评论

iefreer 2017-01-02 23:08:28

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


请先 登录 再评论.
相关文章
  • Web界面编程状态变化和JS开发框架(React/Angular/Ember)

    UI编程中的一个关键课题就是界面组件化(可复用)以及组件状态管理。稍早一些的windows程序员可能接触过MFC,其界面编程中有一个DDX(DoDataExchange)的机制,...

  • HTTP/2背景和新特性简介

    在前面的一篇文章中已经介绍了

  • 学习使用CSS制作进度条

    进度条是基础的界面控件,可用于多种场合,比如任务完成进度,手机充电状态等。本文介绍一个简单实用的进度条制作方法。预期效果如下图所示:直观上,我们可以把该进度条控件分为2个部分,外部的边界用来表示固定的目标范围,里面的条形部分用来表示当前进度。外部目标范围元素的CSS代码编写如下:.pb-scope

  • Three.js 对象局部坐标转换为世界坐标

    在Three.js中进行顶点几何计算时,一个需要注意的地方是,需要统一坐标系。比如你通过Three.js提供的API创建了一个球体网孔对象,那么默认情况下,各网孔顶点的...

  • WebGL入门教程3 - Canvas、Context、API和绘制一个矩形

    在教程2中,我们已经讲述了计算机图形处理硬件结构和流水线。在本文中,我们将开始讲述WebGL的具体应用程序编程接口(API)。WebGL应用程序编程步骤分为以下几步:
    创建一个canvas元素从canvas中获取webgl渲染...

  • 使用Canvas绘制完美的不完美圆形

    真实世界是不完美的,当我们需要模拟真实世界时,经常需要引入不完美/不规则的形状。比如陨石、雨滴、行星、树叶、绵延的海岸线、云朵等。本文介绍如何基于Canva...

  • Canvas实例教程:图像移动、大小调整和裁剪

    本文介绍如何使用JavaScript和HTML5 Canvas元素来移动、调整大小和...

  • inline-block元素设置overflow:hidden属性导致相邻行内元素向下偏移

    在表单修改界面中常会使用一个标签、一个内容加一个修改按钮来组成单行界面,如图1所示。那么在表单总长度受限的情况下,当中间的邮箱名称过长时,会遮盖到旁边...

  • 如何使用CSS3实现一个平滑的3D文本标题

    要实现3D文本,基本上有3种方法:1. 使用CSS3的投影滤镜(filter: drop-shadow)2. 使用3d建模和CSS3 3d变换来实现(最真实)3. 使用CSS3 text-shadow属性来实现...

  • 如何使用CSS3实现一个3D商品标签

    使用3D缎带形状的标签是常见的一个设计模式,用在商品折扣、文章标题或网站推荐信息上,来突出显示重点内容,吸引用户视觉焦点。实现的方法有2种,一种是使用背...

  • 如何使用CSS3实现书页(书本)卷角效果

    我们有时候想在页面显示一个公告或用户提示信息。一个常用设计是使用书签形状。我们可以给书签添加卷角效果,以使其更为逼真。所谓的“卷角”实际上可以用小角度...

  • 更多...