3个经常被问到的 JavaScript 面试题

原文链接

题目 #1: 事宜托付

事宜托付,也叫事宜委派,事宜代办。

当构建应用顺序时,偶然须要将事宜监听器绑定到页面上的某些元素上,以便在用户与元素交互时实行某些操纵。

假定我们如今有一个无序列表:

<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>

我们须要在<li>上绑定点击事宜,我们可能会如许操纵:

app = document.getElementById('todo-app');
let items = app.getElementsByClassName('item');

// 将事宜侦听器绑定到每一个列表项
for (let item of items) {
  item.addEventListener('click', function() {
    alert('you clicked on item: ' + item.innerHTML);
  });
}

虽然如许能够完成功用,但题目是要零丁将事宜侦听器绑定到每一个列表项。这是4个元素,没什么大题目,但假如列表中有10,000个事项,怎么办?这个函数将会建立10,000个自力的事宜监听器,并将每一个事宜监听器绑定到 DOM 。如许代码实行的效力异常低下

更高效的处理计划是将一个事宜侦听器现实绑定到父容器<ul>上,然后在现实单击时能够接见每一个确实元素。这被称为事宜托付,而且它比每一个元素零丁绑定事宜的处置惩罚顺序更高效。

那末上面的代码能够改变成:

let app = document.getElementById('todo-app');
  
// 事宜侦听器绑定到悉数容器上
app.addEventListener('click', function(e) {
  if (e.target && e.target.nodeName === 'LI') {
    let item = e.target;
    alert('you clicked on item: ' + item.innerHTML);
  }
});

题目 #2: 在轮回内运用闭包(Closures)

闭包的实质是一个内部函数接见其作用域以外的变量。闭包能够用于完成诸如 私有变量 和 建立工场函数之类的东西。

在口试中我们可能会见到一段如许的代码:

for (var i = 0; i < 4; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}

运转上面的代码控制台会在1秒后打印4个4,而不是0,1,2,3。

其缘由是由于setTimeout函数建立了一个能够接见其外部作用域的函数(也就是我们常常说的闭包),每一个轮回都包含了索引i

1秒后,该函数被实行而且打印出i的值,其在轮回结束时为4,由于它的轮回周期阅历了0,1,2,3,4,而且轮回终究在4时住手。

下面枚举两种计划处理这个题目:

for (var i = 0; i < 4; i++) {
  // 经由过程通报变量 i
  // 在每一个函数中都能够获取到准确的索引
  setTimeout(function(j) {
    return function() {
      console.log(j);
    }
  }(i), 1000);
}
for (let i = 0; i < 4; i++) {
  // 运用ES6的let语法,它会建立一个新的绑定
  // 每一个要领都是被零丁挪用的
  setTimeout(function() {
    console.log(i);
  }, 1000);
}

题目 #3: 函数防抖(Debouncing)

有一些浏览器事宜能够在很短的时候内疾速启动屡次,比方页面转动事宜。假如将事宜侦听器绑定到窗口转动事宜上,而且用户疾速转动页面,事宜极可能会在短时候屡次触发。这可能会致使一些严峻的机能题目。

因而,在侦听转动,窗口调解大小,或键盘按下的事宜时,请务必运用函数防抖动(Debouncing)函数撙节(Throttling)来提拔页面速率和机能。

函数防抖(Debouncing)是处理这个题目的一种体式格局,经由过程限定须要经由的时候,直到再次挪用函数。一个完成函数防抖的要领是:把多个函数放在一个函数里挪用,隔肯定时候实行一次。

这里有一个运用原生JavaScript完成的例子,用到了作用域、闭包、this和定时事宜:

function debounce(fn, delay) {
  // 耐久化一个定时器 timer
  let timer = null;
  // 闭包函数能够接见 timer
  return function() {
    // 经由过程 'this' 和 'arguments' 取得函数的作用域和参数
    let self = this;
    let args = arguments;
    // 假如事宜被触发,消灭 timer 并重新开始计时
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(self, args);
    }, delay);
  }
}

// 当用户转动时挪用函数foo()
function foo() {
  console.log('You are scrolling!');
} 

// 在事宜触发的两秒后,包裹在debounce()中的函数才会被触发
window.addEventListener('scroll', debounce(foo, 2000));

函数撙节是另一个相似函数防抖的技能,除了运用守候一段时候再挪用函数的要领,函数撙节还限定牢固时候内只能挪用一次。所以,假如一个事宜在100毫秒内发作10次,函数撙节会每2秒挪用一次函数,而不是100毫秒内悉数挪用。

(完)

    原文作者:小小赵老汉
    原文地址: https://segmentfault.com/a/1190000008562917
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞