 相关推荐:2021年大前端面试题汇总(收藏)
每个 JavaScript 程序员都必须知道闭包是什么。在 JavaScript 面试中,你很可能会被问到闭包的概念。 以下是 7 个有关 JavaScript 闭包的面试题,比较有挑战性。 不要查看答案或运行代码,看看自己的水平到底如何。做完这些题大约需要半小时左右。 1. 范围有以下函数 clickHandler,immediate和delayedReload: let countClicks = 0;
button.addEventListener('click', function clickHandler() {
countClicks++;
});
const result = (function immediate(number) {
const message = `number is: ${number}`;
return message;
})(100);
setTimeout(function delayedReload() {
location.reload();
}, 1000);这3个函数中哪个能够访问外部范围变量? 答案clickHandler 能够从外部作用域访问变量 countClicks。
immediate 无法访问外部作用域中的任何变量。
delayedReload 从全局作用域(也就是最外层作用域)中访问全局变量 location。
相关教程推荐:javascript视频教程 2. 丢失的参数下列代码输出什么: (function immediateA(a) {
return (function immediateB(b) {
console.log(a); // => ?
})(1);
})(0);答案输出为:0 用参数 0 调用 immediateA,因此 a 参数为 0。 immediateB 函数嵌套在 immediateA 函数中,是一个闭包,它从外部 immediateA 作用域中得到 a 变量,其中 a 为 0。因此 console.log(a) 的输出为 0。
3. 谁是谁下面的代码将会输出什么内容? let count = 0;
(function immediate() {
if (count === 0) {
let count = 1;
console.log(count); // 输出什么?
}
console.log(count); // 输出什么?
})();答案输出 1 和 0 第一个语句 let count = 0 声明了一个变量 count。 immediate() 是一个闭包,它从外部作用域得到 count 变量。在 immediate() 函数作用域内, count 是 0。
但是,在条件内,另一个 let count = 1 声明了局部变量 count,该变量覆盖了作用域之外的 count。第一个 console.log(count) 输出 1。 第二个 console.log(count) 输出为 0 ,因为这里的 count 变量是从外部作用域访问的。 4. 棘手的闭包下列代码输出什么: for (var i = 0; i < 3; i++) {
setTimeout(function log() {
console.log(i); // => ?
}, 1000);
}答案输出:3, 3, 3。 代码分为两个阶段执行。 阶段1 for() 重复 3 次。在每次循环都会创建一个新函数 log(),该函数将捕获变量 i。 setTimout() 安排log() 在 1000 毫秒后执行。- 当
for() 循环完成时,变量 i 的值为 3。
阶段2 第二阶段发生在 1000ms 之后: setTimeout() 执行预定的 log() 函数。 log() 读取变量 i 当前的值 3,并输出 3
所以输出 3, 3, 3。 5. 错误的信息下面的代码将会输出什么: function createIncrement() {
let count = 0;
function increment() {
count++;
}
let message = `Count is ${count}`;
function log() {
console.log(message);
}
return [increment, log];
}
const [increment, log] = createIncrement();
increment();
increment();
increment();
log(); // => ?答案输出:'Count is 0' increment() 函数被调用 3 次,将 count 增加到 3。
message 变量存在于 createIncrement() 函数的作用域内。其初始值为 'Count is 0'。但即使 count 变量已经增加了几次,message 变量的值也始终为 'Count is 0'。
log() 函数是一个闭包,它从 createIncrement() 作用域中获取 message 变量。 console.log(message) 输出录'Count is 0'到控制台。
6. 重新封装下面的函数 createStack() 用于创建栈结构: function createStack() {
return {
items: [],
push(item) {
this.items.push(item);
},
pop() {
return this.items.pop();
}
};
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => [10]
stack.items = [10, 100, 1000]; // 栈结构的封装被破坏了它能正常工作,但有一个小问题,因为暴露了 stack.items 属性,所以任何人都可以直接修改 items 数组。 这是一个大问题,因为它破坏了栈的封装:应该只有 push() 和 pop() 方法是公开的,而 stack.items 或其他任何细节都不能被访问。 使用闭包的概念重构上面的栈实现,这样就无法在 createStack() 函数作用域之外访问 items 数组: function createStack() {
// 把你的代码写在这里
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => undefined答案以下是对 createStack() 的重构: function createStack() {
const items = [];
return {
push(item) {
items.push(item);
},
pop() {
return items.pop();
}
};
}
const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5
stack.items; // => undefineditems 已被移至 createStack() 作用域内。
这样修改后,从 createStack() 作用域的外部无法访问或修改 items 数组。现在 items 是一个私有变量,并且栈被封装:只有 push() 和 pop() 方法是公共的。 push() 和 pop() 方法是闭包,它们从 createStack() 函数作用域中得到 items 变量。
7. 智能乘法编写一个函数 multiply() ,将两个数字相乘: function multiply(num1, num2) {
// 把你的代码写在这里...
}要求: 如果用 2 个参数调用 multiply(num1,numb2),则应返回这 2 个参数的乘积。 但是如果用 1个参数调用,则该函数应返回另一个函数: const anotherFunc = multiply(num1) 。返回的函数在调用 anotherFunc(num2) 时执行乘法 num1 * num2。 multiply(4, 5); // => 20
multiply(3, 3); // => 9
const double = multiply(2);
double(5); // => 10
double(11); // => 22 答案以下是 multiply() 函数的一种实现方式: function multiply(number1, number2) {
if (number2 !== undefined) {
return number1 * number2;
}
return function doMultiply(number2) {
return number1 * number2;
};
}
multiply(4, 5); // => 20
multiply(3, 3); // => 9
const double = multiply(2);
double(5); // => 10
double(11); // => 22如果 number2 参数不是 undefined,则该函数仅返回 number1 * number2。 但是,如果 number2 是 undefined,则意味着已经使用一个参数调用了 multiply() 函数。这时就要返回一个函数 doMultiply(),该函数稍后被调用时将执行实际的乘法运算。 doMultiply() 是闭包,因为它从 multiply() 作用域中得到了number1 变量。
总结如果你答对了 5 个以上,说明对闭包掌握的很好。如果你答对了不到 5 个,则需要好好的复习一下了。 原文地址:https://dmitripavlutin.com/simple-explanation-of-javascript-closures/ 转载地址:https://segmentfault.com/a/1190000039366748
更多编程相关知识,请访问:编程视频!! 以上就是7个JavaScript中关于闭包的面试题,你能回答上来吗?的详细内容,更多请关注模板之家(www.mb5.com.cn)其它相关文章! |