掌握Javascript面试:什么是闭包?

简介: 文章来源于:https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36在JavaScript的面试中我通常将这个问题放在第一个或者最后一个问题。

文章来源于:https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36

在JavaScript的面试中我通常将这个问题放在第一个或者最后一个问题。坦白地说,如果你没有深入的学习闭包你的JavaScript不可能有很深的造诣。

你可能JavaScript稍好点儿,但你真的理解如何构建一个好的JavaScript应用吗?你真的理解什么正在运行,或者应用如何工作的吗?我对此表示怀疑。不知道这个问题的答案在面试的过程中是一个危险的信号。

你不仅应该知道闭包的工作机制是什么,你还应该知道他为什么发生,并且你应该很轻松的回答几种常用的闭包用例。

闭包常用在JavaScript对象的数据私有化,事件句柄,回调函数,和在局部应用,柯里化,以及其他功能的变成形式。

我不在乎面试候选人是否知道‘closure’这个词语或者技术定义。我想要弄明白的是他们是否理解基本的运行机制。如果他们不知道,显而易见这些面试候选者并没有大量的实际JavaScript应用开发经验。

“如果你不能回答这个问题,你就是一个初级开发人员。我不管你工作了几年。”

这听起来意味着什么,但实际上并不是。我的意思是大多数称职的面试官会问你什么是闭包,并且在大多数时候你回答错误将失去这份工作。如果你足够幸运的话,你将得到一个offer,他们将给你一个初级开发人员的工资而不是一个高级的开发人员。

准备好快速跟进:“你能说出两种常用的闭包吗?”

什么是闭包?

闭包就是一个函数(封闭的)的集合引用的环境(词法环境)状态。换句话说,闭包有能力从一个内部函数访问外部函数的作用域。在JavaScript中,在函数被创建时,每次一个函数被创建闭包也被创建。

用一个闭包,只需在一个函数内部定义一个函数,暴露这个内部的函数,然后返回这个函数,或者把它传递给另一个函数。内部的函数将有能力访问外部函数作用域的变量,即使外部的函数有返回值

使用闭包(实例)

刨除其他的,闭包通常用于对象的数据私有化。数据的私有化是帮助我们开发接口的一个重要的属性,而不是实现(应用的开发的细节实现)。他是一个帮助我们开发一个稳健的软件的重要概念,因为实现细节往往比接口约定更容易被打破。

“程序之于接口,而不是实现”

设计模式:可重用的面向对象软件的元素

在javascript中闭包是的主要机制就是被用来实现数据的私有化。当你用笔包进行数据的私有化,所包含的变量仅被包含在在外部的函数作用域内。除了通过对象的特权方法外,你将不能从外部范围获取数据。在闭包的范围内定义的任何公开方法都是特权的。例如:

const getSecret = (secret) => {
  return {
    get: () => secret
  };
};

test('Closure for object privacy.', assert => {
  const msg = '.get() should have access to the closure.';
  const expected = 1;
  const obj = getSecret(1);

  const actual = obj.get();

  try {
    assert.ok(secret, 'This throws an error.');
  } catch (e) {
    assert.ok(true, `The secret var is only available
      to privileged methods.`);
  }

  assert.equal(actual, expected, msg);
  assert.end();
});

在上面的例子中,‘.get()’方法是在‘getsecret()’范围内定义的,这使得它可以从‘getsecret()’访问任何变量,并使它 成为一个特权方法。

使对象的数据私有化并不是闭包的唯一用途。它也可以用来创建有状态的函数,这些函数的返回值可能受他们内部状态的影响。示例如下:

const secret = msg => () => msg;

// Secret - creates closures with secret messages.
// https://gist.github.com/ericelliott/f6a87bc41de31562d0f9
// https://jsbin.com/hitusu/edit?html,js,output

// secret(msg: String) => getSecret() => msg: String
const secret = (msg) => () => msg;

test('secret', assert => {
  const msg = 'secret() should return a function that returns the passed secret.';

  const theSecret = 'Closures are easy.';
  const mySecret = secret(theSecret);

  const actual = mySecret();
  const expected = theSecret;

  assert.equal(actual, expected, msg);
  assert.end();
});

在函数式编程中,闭包常常被用在局部应用&柯里化编程,这里需要明白一些定义:
应用程序:应用一个函数的参数已返回一个值得过程
部分应用:函数应用他的部分参数的过程,这个部分被应用的函数稍后被用来获得返回值。换句话来说,一个函数转变一个多参数的函数,并利用它的返回一个少参数的函数。

部分应用利用闭包的作用域来处理参数对象,你可以写一个泛型函数部分的将参数应用于目标函数,下面有一个示例:

partialApply(targetFunction: Function, ...fixedArgs: Any[]) =>
    functionWithFewerParams(...remainingArgs: Any[])

它将接受一个带有任意数量参数的函数,接下来我们想要部分的应用函数的参数然后返回一个带有剩余参数的函数。

下面一个例子,一个求两个数字和的函数:

const add = (a, b) => a + b;

现在你想要一个实现对任意数字都加10的函数,我们命名它为‘add10()’。‘add10(5)’的结果应该是‘15’,我们顶一个‘partialAply()’的函数,如下:

const add10 = partialApply(add, 10);
add10(5);

在这个例子中,参数‘10’变成了一个固定的参数被保存在‘add10()’的闭包作用域中。
下面是‘partialApply()’的实现代码:

// Generic Partial Application Function
// https://jsbin.com/biyupu/edit?html,js,output
// https://gist.github.com/ericelliott/f0a8fd662111ea2f569e

// partialApply(targetFunction: Function, ...fixedArgs: Any[]) =>
//   functionWithFewerParams(...remainingArgs: Any[])
const partialApply = (fn, ...fixedArgs) => {
  return function (...remainingArgs) {
    return fn.apply(this, fixedArgs.concat(remainingArgs));
  };
};
test('add10', assert => {
  const msg = 'partialApply() should partially apply functions'
  const add = (a, b) => a + b;
  const add10 = partialApply(add, 10);
  const actual = add10(5);
  const expected = 15;

  assert.equal(actual, expected, msg);
});

正如我们从上面的示例中看到的,这个简单的返回函数可以访问‘fixArgs’参数,这个参数是从‘partialApply()’中传入的。

未经许可不得转载!

相关文章
|
1月前
|
JavaScript 前端开发
常见的JS面试题
【8月更文挑战第5天】 常见的JS面试题
50 3
|
3天前
|
JSON JavaScript 前端开发
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
|
2天前
|
前端开发 JavaScript
JavaScript 面试系列:如何理解 ES6 中 Generator ?常用使用场景有哪些?
JavaScript 面试系列:如何理解 ES6 中 Generator ?常用使用场景有哪些?
|
8天前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:从基础概念到实际应用
本文深入探讨了JavaScript中闭包的概念,从定义、作用域链和实际应用等方面进行了详细阐述。通过生动的比喻和实例代码,帮助读者理解闭包在函数执行上下文中的重要性,以及如何在实际开发中有效利用闭包解决复杂问题。同时,文章也指出了过度使用闭包可能导致的潜在问题,并给出了相应的优化建议。
|
1月前
|
存储 JavaScript 前端开发
2022年前端js面试题
2022年前端js面试题
21 0
|
1月前
|
JavaScript 前端开发 安全
详细讲解JavaScript中的闭包问题附代码演示
闭包是JavaScript中一关键概念,它允许内部函数访问外部函数的作用域,从而实现变量的封装与持久化。本文通过示例解释了闭包的工作原理及其优势,如数据隐藏和私有变量的实现;同时也指出了闭包可能导致的内存占用问题,强调合理使用的重要性。
21 1
|
1月前
|
JavaScript 前端开发 Java
JavaScript中的闭包概念讲解
闭包是指函数内部嵌套另一个函数,并且内部函数引用了外部函数的数据(如变量或函数)。这样的内部函数被称为闭包。以示例代码为例,`fn1` 中有两个闭包函数 `fn2` 和 `fn3`,它们都可以访问并修改 `fn1` 中的变量 `a`。
13 1
|
21天前
|
自然语言处理 JavaScript 前端开发
|
1月前
|
JavaScript 前端开发 程序员
JS小白请看!一招让你的面试成功率大大提高——规范代码
JS小白请看!一招让你的面试成功率大大提高——规范代码
|
29天前
|
自然语言处理 前端开发 JavaScript
前端进阶必读:JS闭包深度解析,掌握这一特性,你的代码将焕然一新!
【8月更文挑战第23天】闭包是JavaScript的一项高级功能,让函数能够访问和操作外部函数作用域中的变量。本文深入解析闭包概念、组成及应用场景。闭包由函数及其词法环境构成,通过在一个函数内定义另一个函数来创建。它有助于封装私有变量、维持状态和动态生成函数。然而,不当使用闭包可能导致内存泄漏或性能问题。掌握闭包对于实现模块化代码和成为优秀前端开发者至关重要。
30 0