加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

Web前端:征服 JavaScript 面试之什么是闭包?

发布时间:2019-07-09 18:54:14 所属栏目:建站 来源:牛旦教育IT课堂
导读:前言 在我面试时问出的一系列问题里,闭包通常是我问的第一个或最后一个问题。坦白地说,如果你连闭包也弄不明白,你是不会在 JavaScript 的道路上走多远的。 你别东张西望,说的就是你。你真的理解如何构建一个严谨的 JavaScript 应用?你真的理解代码背后
副标题[/!--empirenews.page--]

 前言

在我面试时问出的一系列问题里,闭包通常是我问的第一个或最后一个问题。坦白地说,如果你连闭包也弄不明白,你是不会在 JavaScript 的道路上走多远的。

你别东张西望,说的就是你。你真的理解如何构建一个严谨的 JavaScript 应用?你真的理解代码背后发生的事情或者说一个应用程序是如何工作的?我表示怀疑。如果连个闭包问题都搞不清的话,真是有点够呛。

Web前端:征服 JavaScript 面试之什么是闭包?

你不仅仅应该了解闭包的机制,更应该了解闭包为什么很重要,以及能够很容易地回答出闭包的几种可能的应用场景。

闭包在 JavaScript 中常用来实现对象数据的私有,在事件处理和回调函数中也常常会用到它,此外还有偏函数应用(partial applications)和柯里化(currying),以及其他函数式编程模式。

我不在乎面试者是否知道“closure”这个单词或者它的专业定义。我只想弄清他们是否理解基本原理。如果他们没有,那么通常意味着这些面试者在构建实际 JavaScript 应用方面并没有很多经验。

如果你不能回答这个问题,你只是个初级开发者。不管你实际上已经干这个多久了。

为了快速理解下面的内容:你想一下能否举出两个闭包的通用场景?

什么是闭包?

简言之,闭包是由函数引用其周边状态(词法环境)绑在一起形成的(封装)组合结构。在 JavaScript 中,闭包在每个函数被创建时形成。

这是基本原理,但为什么我们关心这些?实际上,由于闭包与它的词法环境绑在一起,因此闭包让我们能够从一个函数内部访问其外部函数的作用域。

要使用闭包,只需要简单地将一个函数定义在另一个函数内部,并将它暴露出来。要暴露一个函数,可以将它返回或者传给其他函数。

内部函数将能够访问到外部函数作用域中的变量,即使外部函数已经执行完毕。

闭包使用的例子

闭包的用途之一是实现对象的私有数据。数据私有是让我们能够面向接口编程而不是面向实现编程的基础。而面向接口编程是一个重要的概念,有助于我们创建更加健壮的软件,因为实现细节比接口约定相对来说更加容易被改变。

“面向接口编程,别面向实现编程。” 设计模式:可复用面向对象软件的要素

在 JavaScript 中,闭包是用来实现数据私有的原生机制。当你使用闭包来实现数据私有时,被封装的变量只能在闭包容器函数作用域中使用。你无法绕过对象被授权的方法在外部访问这些数据。在 JavaScript 中,任何定义在闭包作用域下的公开方法才可以访问这些数据。例如:

  1. const getSecret = (secret) => { 
  2.  return { 
  3.  get: () => secret 
  4.  }; 
  5. }; 
  6. test('Closure for object privacy.', assert => { 
  7.  const msg = '.get() should have access to the closure.'; 
  8.  const expected = 1; 
  9.  const obj = getSecret(1); 
  10.  const actual = obj.get(); 
  11.  try { 
  12.  assert.ok(secret, 'This throws an error.'); 
  13.  } catch (e) { 
  14.  assert.ok(true, `The secret var is only available 
  15.  to privileged methods.`); 
  16.  } 
  17.  assert.equal(actual, expected, msg); 
  18.  assert.end(); 
  19. }); 

在上面的例子里,get() 方法定义在 getSecret() 作用域下,这让它可以访问任何 getSecret()中的变量,于是它就是一个被授权的方法。在这个例子里,它可以访问参数 secret。

对象不是唯一的产生私有数据的方式。闭包还可以被用来创建有状态的函数,这些函数的执行过程可能由它们自身的内部状态所决定。例如:

  1. const secret = (msg) => () => msg; 
  2. // Secret - creates closures with secret messages. 
  3. // https://gist.github.com/ericelliott/f6a87bc41de31562d0f9 
  4. // https://jsbin.com/hitusu/edit?html,js,output 
  5. // secret(msg: String) => getSecret() => msg: String 
  6. const secret = (msg) => () => msg; 
  7. test('secret', assert => { 
  8.  const msg = 'secret() should return a function that returns the passed secret.'; 
  9.  const theSecret = 'Closures are easy.'; 
  10.  const mySecret = secret(theSecret); 
  11.  const actual = mySecret(); 
  12.  const expected = theSecret; 
  13.  assert.equal(actual, expected, msg); 
  14.  assert.end(); 
  15. }); 

在函数式编程中,闭包经常用于偏函数应用和柯里化。为了说明这个,我们先定义一些概念:

函数应用:一个过程,指将参数传给一个函数,并获得它的返回值。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读