13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

这7道关于闭包的面试题,你能答对几个?

每个 JavaScript 程序员都必须知道闭包是什么。在 JavaScript 面试中,你很可能会被问到闭包的概念。

在吉木萨尔等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都做网站、成都网站建设、成都外贸网站建设 网站设计制作按需网站开发,公司网站建设,企业网站建设,成都品牌网站建设,全网整合营销推广,外贸网站制作,吉木萨尔网站建设费用合理。

以下是 7 个有关 JavaScript 闭包的面试题,比较有挑战性。

不要查看答案或运行代码,看看自己的水平到底如何。做完这些题大约需要半小时左右。

1.  热身

有以下函数 clickHandler,immediate和delayedReload:

 
 
 
  1. let countClicks = 0; 
  2. button.addEventListener('click', function clickHandler() { 
  3.   countClicks++; 
  4. }); 
  5. const result = (function immediate(number) { 
  6.   const message = `number is: ${number}`; 
  7.   return message; 
  8. })(100); 
  9. setTimeout(function delayedReload() { 
  10.   location.reload(); 
  11. }, 1000); 

这3个函数中哪个能够访问外部范围变量?

答案:

2. 丢失的参数

下列代码输出什么:

 
 
 
  1. (function immediateA(a) { 
  2.   return (function immediateB(b) { 
  3.     console.log(a); // => ? 
  4.   })(1); 
  5. })(0); 

答案:

3. 谁是谁

下面的代码将会输出什么内容?

 
 
 
  1. let count = 0; 
  2. (function immediate() { 
  3.   if (count === 0) { 
  4.     let count = 1; 
  5.     console.log(count); // 输出什么? 
  6.   } 
  7.   console.log(count); // 输出什么? 
  8. })(); 

答案:

但是,在条件内,另一个 let count = 1 声明了局部变量 count,该变量覆盖了作用域之外的 count。第一个 console.log(count) 输出 1。

第二个 console.log(count) 输出为 0 ,因为这里的 count 变量是从外部作用域访问的。

4. 棘手的闭包

下列代码输出什么:

 
 
 
  1. for (var i = 0; i < 3; i++) { 
  2.   setTimeout(function log() { 
  3.     console.log(i); // => ? 
  4.   }, 1000); 

答案输出:

阶段1:

阶段2:

第二阶段发生在 1000ms 之后:

5. 错误的信息

下面的代码将会输出什么:

 
 
 
  1. function createIncrement() { 
  2.   let count = 0; 
  3.   function increment() {  
  4.     count++; 
  5.   } 
  6.  
  7.   let message = `Count is ${count}`; 
  8.   function log() { 
  9.     console.log(message); 
  10.   } 
  11.    
  12.   return [increment, log]; 
  13.  
  14. const [increment, log] = createIncrement(); 
  15. increment();  
  16. increment();  
  17. increment();  
  18. log(); // => ? 

答案:

输出:'Count is 0'

6. 重新封装

下面的函数 createStack() 用于创建栈结构:

 
 
 
  1. function createStack() { 
  2.   return { 
  3.     items: [], 
  4.     push(item) { 
  5.       this.items.push(item); 
  6.     }, 
  7.     pop() { 
  8.       return this.items.pop(); 
  9.     } 
  10.   }; 
  11.  
  12. const stack = createStack(); 
  13. stack.push(10); 
  14. stack.push(5); 
  15. stack.pop(); // => 5 
  16.  
  17. stack.items; // => [10] 
  18. stack.items = [10, 100, 1000]; // 栈结构的封装被破坏了 

它能正常工作,但有一个小问题,因为暴露了 stack.items 属性,所以任何人都可以直接修改 items 数组。

这是一个大问题,因为它破坏了栈的封装:应该只有 push() 和 pop() 方法是公开的,而 stack.items 或其他任何细节都不能被访问。

使用闭包的概念重构上面的栈实现,这样就无法在 createStack() 函数作用域之外访问 items 数组:

 
 
 
  1. function createStack() { 
  2.   // 把你的代码写在这里 
  3.  
  4. const stack = createStack(); 
  5. stack.push(10); 
  6. stack.push(5); 
  7. stack.pop(); // => 5 
  8.  
  9. stack.items; // => undefined 

答案:

以下是对 createStack() 的重构:

 
 
 
  1. function createStack() { 
  2.   const items = []; 
  3.   return { 
  4.     push(item) { 
  5.       items.push(item); 
  6.     }, 
  7.     pop() { 
  8.       return items.pop(); 
  9.     } 
  10.   }; 
  11.  
  12. const stack = createStack(); 
  13. stack.push(10); 
  14. stack.push(5); 
  15. stack.pop(); // => 5 
  16.  
  17. stack.items; // => undefined 

items 已被移至 createStack() 作用域内。

这样修改后,从 createStack() 作用域的外部无法访问或修改 items 数组。现在 items 是一个私有变量,并且栈被封装:只有 push() 和 pop() 方法是公共的。

push() 和 pop() 方法是闭包,它们从 createStack() 函数作用域中得到 items变量。

7. 智能乘法

编写一个函数 multiply() ,将两个数字相乘:

 
 
 
  1. function multiply(num1, num2) { 
  2.   // 把你的代码写在这里... 

要求:

如果用 2 个参数调用 multiply(num1,numb2),则应返回这 2 个参数的乘积。

但是如果用 1个参数调用,则该函数应返回另一个函数:const anotherFunc = multiply(num1) 。返回的函数在调用 anotherFunc(num2) 时执行乘法 num1 * num2。

 
 
 
  1. multiply(4, 5); // => 20 
  2. multiply(3, 3); // => 9 
  3.  
  4. const double = multiply(2); 
  5. double(5);  // => 10 
  6. double(11); // => 22 

答案:

以下是 multiply() 函数的一种实现方式:

 
 
 
  1. function multiply(number1, number2) { 
  2.   if (number2 !== undefined) { 
  3.     return number1 * number2; 
  4.   } 
  5.   return function doMultiply(number2) { 
  6.     return number1 * number2; 
  7.   }; 
  8.  
  9. multiply(4, 5); // => 20 
  10. multiply(3, 3); // => 9 
  11.  
  12. const double = multiply(2); 
  13. double(5);  // => 10 
  14. double(11); // => 22 

如果 number2 参数不是 undefined,则该函数仅返回 number1 * number2。

但是,如果 number2 是 undefined,则意味着已经使用一个参数调用了 multiply() 函数。这时就要返回一个函数 doMultiply(),该函数稍后被调用时将执行实际的乘法运算。

doMultiply() 是闭包,因为它从 multiply() 作用域中得到了number1 变量。


本文名称:这7道关于闭包的面试题,你能答对几个?
URL标题:http://cdbrznjsb.com/article/dhecejc.html

其他资讯

让你的专属顾问为你服务