ホームページ >ウェブフロントエンド >jsチュートリアル >注意すべき 3 つの JavaScript 面接の質問

注意すべき 3 つの JavaScript 面接の質問

怪我咯
怪我咯オリジナル
2017-04-05 14:00:391298ブラウズ

JavaScript は、最新のすべてのブラウザの公用語です。その結果、開発者インタビューでは JavaScript に関する質問がさまざまな言語で行われます。

この記事では、最新の JavaScript ライブラリ、一般的な開発手法、または新しい ES6 関数 については説明しません。その代わりに、面接でよく聞かれる JavaScript に関する 3 つの質問について話しましょう。私がこれらの質問をしたところ、友達も同じように質問したと言っていました。

もちろん、JavaScript の面接の準備をするときに、これら 3 つの質問だけを学べばよいというわけではありません。次の面接に向けてよりよく準備する方法はまだたくさんあります。しかし、面接官はおそらく次の点であなたの理解度を判断します。 3 つの質問と JavaScript と DOM の習得。

始めましょう!以下の例ではネイティブ JavaScript を使用していることに注意してください。面接官は通常、ライブラリ (jQuery など) の助けを借りずに、あなたが JavaScript と DOM をどの程度理解しているかをテストしたいと考えているからです。

質問 1: イベント プロキシ

アプリケーションを作成するとき、ページ上のボタン、テキスト、または画像にイベント リスナーを追加し、ユーザーがこれらの要素を操作するときに特定のアクションをトリガーする必要がある場合があります。

例として、単純な To-Do リストを考えてみましょう。面接官は、ユーザーがリスト内の項目をクリックしたときにアクションをトリガーしたいと伝えます。そして、JavaScript を使用して、次の HTML コードに従ってこの関数を実装しましょう:

<ul id="todo-app">
  <li class="item">Walk the dog</li>
  <li class="item">Pay bills</li>
  <li class="item">Make dinner</li>
  <li class="item">Code for one hour</li>
</ul>

次のコードのようにイベント リスナーを要素に追加できます:

document.addEventListener(&#39;DOMContentLoaded&#39;, function() {

  let app = document.getElementById(&#39;todo-app&#39;);
  let items = app.getElementsByClassName(&#39;item&#39;);

  // 给每个列表项添加事件监听器
  for (let item of items) {
    item.addEventListener(&#39;click&#39;, function() {
      alert(&#39;you clicked on item: &#39; + item.innerHTML);
    });
  }

});

もちろん、上記のコードは面接官のニーズを満たすことができます。つまり、各リスト項目にはイベント リスナーが追加されます。リストに項目が 4 つしかない場合は問題ありませんが、誰かが To Do リスト に 10,000 項目を追加した場合はどうなるでしょうか (おそらく、やるべきことが山ほどあるでしょう)。その時点で、関数は 10,000 個のイベント リスナーを作成し、それらすべてを DOM に追加します。この効率は非常に低いです。

面接中、最初に、ユーザーが追加できる To Do アイテムの数を最大でいくつまで面接官に尋ねるのが最善です。 10 を超えることがない場合、上記のコードは問題なく実行されます。しかし、ユーザーが入力できる To Do 項目の数に制限がない場合は、より効率的なソリューションを見つける必要があります。

アプリケーションに何百ものイベント リスナーがある場合、より効率的な解決策は、最も外側のコンテナに

イベント リスナーを追加し、ユーザーが実際にクリックしたときに実際にクリックされた To Do 項目を取得することです。これはイベント デリゲートと呼ばれ、各 To Do アイテムに個別のイベント リスナーを追加するよりも効率的です。

イベント デリゲートのコードは次のとおりです:

document.addEventListener(&#39;DOMContentLoaded&#39;, function() {

  let app = document.getElementById(&#39;todo-app&#39;);

  // 给容器添加事件监听器
  app.addEventListener(&#39;click&#39;, function(e) {
    if (e.target && e.target.nodeName === &#39;LI&#39;) {
      let item = e.target;
      alert(&#39;you clicked on item: &#39; + item.innerHTML);
    }
  });

});

質問 #2: ループ内でクロージャを使用する

面接官はこの質問への回答を通じてあなたの言語への精通度を判断できるため、クロージャは面接でよく質問されます。クロージャをいつ使用するかがわかります。

クロージャは、スコープ外の

変数にアクセスできる内部関数です。クロージャを使用して、民営化を実装し、ファクトリ機能を作成できます。クロージャに関するよくあるインタビューの質問は次のとおりです:

整数

配列をループし、3秒の遅延で配列内の各要素のインデックスを出力する関数を作成してください。 この問題の一般的な (間違った) 実装は次のとおりです:

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
  setTimeout(function() {
    console.log(&#39;The index of this number is: &#39; + i);
  }, 3000);
}

この関数を実行すると、3 秒後に毎回

4

が、予想される 0, 1, 2 , の代わりに出力されることがわかります。 3この状況の理由を正しく見つけるには、JavaScript がこのコードをどのように実行するかを理解する必要があります。これが面接官があなたを調べたいことです。

その理由は、setTimeout 関数が外側のスコープ、つまりインデックス i を含むループにアクセスする関数 (クロージャ) を作成するためです。 3 秒後、関数は i の値の出力を開始し、ループはこの時点で終了します。i の値はすでに 4 です。 0、1、2、3、4とループして、最終的に4で止まるからです。

この問題を正しく解決するには、実際にはいくつかの方法があります。

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
  // 给每个函数传入变量 i 让其能访问正确的索引
  setTimeout(function(i_local) {
    return function() {
      console.log(&#39;The index of this number is: &#39; + i_local);
    }
  }(i), 3000);
}
const arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {
  // 使用 ES6 中的 let 关键字,它会在函数调用时创建一个新的绑定
  // 了解更多:http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads
  setTimeout(function() {
    console.log(&#39;The index of this number is: &#39; + i);
  }, 3000);
}

問題 #3: デバウンス

一部のブラウザ イベント (ウィンドウのサイズ変更やページのスクロールなど) は、短期間に複数回トリガーされる可能性があります。ウィンドウ スクロール イベントにイベント リスナーを追加し、ユーザーがページを素早くスクロールし続けると、イベントが 3 秒間に数千回発生する可能性があります。これにより、非常に深刻なパフォーマンスの問題が発生する可能性があります。

インタビューでアプリケーションの構築やスクロール イベント、ウィンドウのサイズ変更イベント、キーボード イベントなどについて議論する場合は、ページの速度とパフォーマンスを向上させる方法としてデバウンスまたはスロットルについて必ず言及してください。 CSS トリックの例を見てみましょう:

2011 年、Twitter には問題がありました。Twitter の概要をスクロールすると、ページが非常に動かなくなったり、応答しなくなったりすることがありました。 John Resig はこの問題についてブログを書き、時間のかかる関数をスクロール イベントに直接バインドすることがいかに悪い考えであるかを説明しました。

Debouncing 是解决这个问题的一种方法,它的做法是限制下次函数调用之前必须等待的时间间隔。正确实现 debouncing 的方法是将若干个函数调用 合成 一次,并在给定时间过去之后仅被调用一次。下面是一个原生 JavaScript 的实现,用到了 作用域 , 闭包, this , 和 计时事件 :

// 将会包装事件的 debounce 函数
function debounce(fn, delay) {
  // 维护一个 timer
  let timer = null;
  // 能访问 timer 的闭包
  return function() {
    // 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量
    let context = this;
    let args = arguments;
    // 如果事件被调用,清除 timer 然后重新设置 timer
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  }
}

这个函数 — 当传入一个事件(fn)时 — 会在经过给定的时间(delay)后执行。

函数这样用:

// 当用户滚动时被调用的函数
function foo() {
  console.log(&#39;You are scrolling!&#39;);
}

// 在 debounce 中包装我们的函数,过 2 秒触发一次
let elem = document.getElementById(&#39;container&#39;);
elem.addEventListener(&#39;scroll&#39;, debounce(foo, 2000));

Throttling 是与 debouncing 类似的一种技术,但它不是在调用函数之前等待一段时间,throttling 是在较长的时间间隔内调用函数。所以如果一个事件每 100 毫秒被触发 10 次,throttling 会在每隔 2 秒时执行一次这个函数,而不是在 100 毫秒内执行 10 次事件。

 

以上が注意すべき 3 つの JavaScript 面接の質問の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。