주의해야 할 JavaScript 면접 질문 3가지

怪我咯
풀어 주다: 2017-04-05 14:00:39
원래의
1273명이 탐색했습니다.

JavaScript는 모든 최신 브라우저의 공식 언어입니다. 결과적으로 개발자 인터뷰에서는 다양한 언어로 JavaScript 질문이 출제됩니다.

이 기사에서는 최신 JavaScript 라이브러리, 일반적인 개발 방식 또는 새로운 ES6 함수를 다루지 않습니다. 대신 면접에서 자주 나오는 자바스크립트 질문 3가지에 대해 이야기해보겠습니다. 나도 이런 질문을 했고, 친구들도 그런 질문을 했다고 한다.

물론 JavaScript 인터뷰를 준비할 때 이 3가지 질문만 배워야 한다는 의미는 아닙니다. 다가오는 인터뷰를 더 잘 준비할 수 있는 방법은 여전히 ​​많이 있지만 면접관이 합격할 가능성이 매우 높습니다. 다음 3가지 질문은 JavaScript와 DOM에 대한 이해와 숙달을 확인하기 위한 것입니다.

시작해 보세요! 면접관은 일반적으로 라이브러리(예: jQuery)의 도움 없이 JavaScript와 DOM을 얼마나 잘 이해하고 있는지 테스트하기를 원하므로 아래 예에서는 기본 JavaScript를 사용하고 있습니다.

질문 #1: 이벤트 프록시

애플리케이션을 생성할 때 페이지의 버튼, 텍스트 또는 그림에 이벤트 리스너를 추가하고 사용자가 상호작용할 때 특정 작업을 트리거해야 하는 경우가 있습니다. 이 요소.

간단한 할 일 목록을 예로 들어 보겠습니다. 면접관은 사용자가 목록에 있는 항목을 클릭하면 작업이 실행되기를 원한다고 말합니다. 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개만 있으면 괜찮지만, 누군가가 자신의 할 일 목록에 10,000개의 새 항목을 추가하면 어떻게 될까요(아마도 할 일이 엄청나게 많을 수도 있습니다)? 이 시점에서 함수는 10,000개의 이벤트 리스너를 생성하고 모두 DOM에 추가합니다. 이 효율성은 매우 낮습니다. 면접 중에는 먼저 사용자가 최대 몇 개의 할일 항목을 추가할 수 있는지 면접관에게 물어보는 것이 가장 좋습니다. 10개를 넘지 않으면 위 코드는 문제 없이 실행됩니다. 그러나 사용자가 입력할 수 있는 할 일 항목의 수에 제한이 없다면 보다 효율적인 솔루션을 찾아야 합니다.

애플리케이션에 수백 개의 이벤트 리스너가 있는 경우 더 효율적인 솔루션은 가장 바깥쪽 컨테이너에

이벤트 리스너를 추가한 다음 사용자가 실제로 클릭할 때 실제 이벤트를 가져오는 것입니다. - 항목을 수행합니다. 이를 이벤트 대리자라고 하며 각 할일 항목에 별도의 이벤트 리스너를 추가하는 것보다 더 효율적입니다. 이벤트 대리자를 위한 코드는 다음과 같습니다.

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);
}
로그인 후 복사
rrree

문제 #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 次事件。

 

위 내용은 주의해야 할 JavaScript 면접 질문 3가지의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿