ホームページ > 記事 > ウェブフロントエンド > JavaScript のクロージャーに関する面接での 7 つの質問、答えることができますか?
関連する推奨事項: 2021 年の主要なフロントエンド面接の質問の概要 (コレクション)
すべての JavaScript プログラマーが知っておくべきこと閉鎖です。 JavaScript の面接では、おそらくクロージャーの概念について質問されるでしょう。
以下は、JavaScript クロージャーに関する面接でのさらに難しい 7 つの質問です。
自分の実力を確かめるために、答えを見たり、コードを実行したりしないでください。これらの質問を完了するには約 30 分かかります。
には、次の関数 clickHandler
、immediate
、および layedReload
があります。 # #
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 外部スコープ内の変数にはアクセスできません。
layedReload グローバル スコープ (つまり、最も外側のスコープ) からグローバル変数
location にアクセスします。
(function immediateA(a) { return (function immediateB(b) { console.log(a); // => ? })(1); })(0);
0
0immediateA
なので、
a パラメータは
0 です。
immediateB
immediateA 関数にネストされた関数は、外側の
immediateA スコープ ## 変数から
a# を取得するクロージャです。ここで、a
は 0
です。したがって、console.log(a)
の出力は 0
になります。
let count = 0; (function immediate() { if (count === 0) { let count = 1; console.log(count); // 输出什么? } console.log(count); // 输出什么? })();答え
と 0
最初のステートメント
は変数 count
を宣言します。
は、外部スコープから count
変数を取得するクロージャです。 immediate()
関数のスコープ内では、count
は 0
です。 ただし、条件内では、別の
がローカル変数 count
を宣言しており、スコープ外の count# をオーバーライドします。最初の
console.log(count) は
1 を出力します。
2 番目の
console.log(count)
0 です。これは、ここの
count 変数が外部スコープからアクセスされているためです。
4. トリッキーなクロージャ
for (var i = 0; i < 3; i++) { setTimeout(function log() { console.log(i); // => ? }, 1000); }
回答
3、
3。
コードは 2 段階で実行されます。
フェーズ 1
for()
が各ループで作成され、変数
i をキャプチャします。
setTimout()
log() が 1000 ミリ秒後に実行されるようにスケジュールします。
for() の値は
3 になります。
2 番目のフェーズは 1000 ミリ秒後に発生します:
setTimeout() 関数。
log() 変数
i
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(); // => ?
increment()
関数が 3 回呼び出され、
が 3
に増加します。 。 message
変数は
関数のスコープ内に存在します。初期値は 'Count is 0'
です。ただし、count
変数が数回増加しても、message
変数の値は常に 'Count is 0'
です。 log()
関数は、
スコープから message
変数を取得するクロージャです。 console.log(message)
ログ 'Count is 0'
をコンソールに出力します。 6. 再パッケージ
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
プロパティが公開されているため、誰でも
配列を直接変更できます。 これは、スタックのカプセル化を破壊するため、大きな問題です。
push()
メソッドと
メソッドのみをパブリックにする必要があり、 stack.items
にもその他の詳細にもアクセスできません。 <p>使用闭包的概念重构上面的栈实现,这样就无法在 <code>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; // => undefined
items
已被移至 createStack()
作用域内。
这样修改后,从 createStack()
作用域的外部无法访问或修改 items
数组。现在 items
是一个私有变量,并且栈被封装:只有 push()
和 pop()
方法是公共的。
push()
和 pop()
方法是闭包,它们从 createStack()
函数作用域中得到 items
变量。
编写一个函数 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
更多编程相关知识,请访问:编程视频!!
以上がJavaScript のクロージャーに関する面接での 7 つの質問、答えることができますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。