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

来源:互联网 发布:淘宝一件代发地址 编辑:程序博客网 时间:2024/06/05 14:24

        你可能置身其中,但你真的懂得如何开发一系列JavaScript应用吗?你真的知道这个应用如何运行的吗?我不相信。不了解这个问题在面试中是很危险的一个信号。

        你不仅应该知道闭包的实现原理,你还应了解为什么它很重要,并且你要能简单的回答几个使用闭包的用例。

        在JavaScript中,闭包常用于数据隐私、事件处理、回调函数以及偏函数应用、柯里化和其他函数式编程范例。

        面试官并不在乎你是否懂得“闭包”这个词或者它的定义。他想要知道面试者是否了解其原理。如果他们不了解,那么智能说明作为开发者,在实际开发JavaScript应用中缺少编程经验。

        如果你无法回答此问题,你只是一个初级开发者。我并不会在意你编程了多久,哪怕10年。

        快速跟进准备回答:你能说出闭包的两个常见用法吗?

什么是闭包?

        简而言之,闭包是将一个函数和对周围状态的引用捆绑(enclosed)在一起的组合。在JavaScript中,闭包在每次一个函数创建时被创建,函数创建时。

        这些是基本原理,但我们为什么要关心它?在实际中,因为闭包用括号“()”捆绑,它能让你从函数内部访问函数外部域。

        要使用闭包,只需在另一个函数中定义一个函数,然后将它暴露给外部。要暴露一个函数,则返回它或将它传递给另一个函数。

        函数内部有权限访问函数外部作用域中的变量,即使在函数外部已经return了。

使用闭包(示例)

        之前说了,闭包通常用于对象的数据隐私。数据隐私是一个重要的属性,有助于我们编写接口,而不是一个实现。这是一个很重要的概念,有助于我们建立更强大更鲁棒的软件,因为实现细节比接口协议更容易改变。

        在JavaScript中,闭包是用于数据隐私的主要机制。当你将闭包用于数据隐私时,所包含的变量只在包含(外)函数的范围内。除了通过对象的特权方法外,你不能从外部域中获得里面的数据。在JavaScript中,定义在闭包域内的任何暴露的方法是享有特权的。例如:

/*interface Obj { get() => Any;} o(secret: Any) => Obj*/const o = (secret) => { return {   get: () => secret };}; test('Closure for object privacy.',assert => { const msg = '.get() should have access to the closure.'; const expected = 1; const obj = o(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()”方法被定义在“o()”域里面,并允许访问“o()”中的任何变量,它就是一个特权方法。例子中的参数为“secret”。

        并不只有对象会产生数据隐私。闭包也可以用来创建有状态的函数,可以通过内部状态来影响其返回值。例如:

// secret(msg: String) =>getSecret() => msg: Stringconst secret = (msg) => () =>msg; test('secret', assert => { const msg = 'secret() should return a function that returns the passedsecret.';  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”。

        我们的“partialApply()”将让它实现:

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

        在上面例子中,参数“10”是一个修正参数,它在“add10()”闭包域内被使用。

        让我们来看下“partialApply()”的实现吧:

const partialApply = (fn, ...fixedArgs)=> { return function (...remainingArgs) {   return fn.apply(this, fixedArgs.concat(remainingArgs)); };};

        正如你所见,它简单的返回一个带有能访问“fixedArgs”参数的函数,此函数我们通过“partialApply()”传入参数fn来实现。

现在轮到你了

        你会怎么使用闭包呢?

0 0
原创粉丝点击