文章泉源:http://mp.weixin.qq.com/s/vs0…
媒介
在民众号上看到了这篇文章,觉得很有效,有助于明白JS进修中的一些重点难点。决议把它整顿下宣布出来。该文章重要引见了JS中的三个题目。在今后的几篇文章里,我会细致引见这三个题目。
文章内容
JavaScript 是一切当代浏览器的官方言语。因而,种种言语的开辟者口试中都邑碰到 JavaScript 题目。
本文不讲最新的 JavaScript 库,通用开辟实践,或任何新的 ES6 函数。而是讲讲口试中经常涌现的 3 个 JavaScript 题目。我问过这些题目,我的朋侪说他们也问。
固然不是说你在预备 JavaScript 口试时只需进修这 3 个题目 —— 你另有许多门路去更好的预备行将到来的口试 —— 但口试官很有能够经由过程下面 3 个题目来推断你相识和控制 JavaScript 和 DOM 的状况。
让我们最先吧!注重下面的例子中我们运用原生 JavaScript, 由于口试官通常想考核你在不借助库(比方 jQuery)的协助时控制 JavaScript 和 DOM 的状况。
题目 #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('DOMContentLoaded', function() {
let 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 上。如许效力异常低。
口试中最好起首问一下口试官用户最多能够增加多少个代办事项。假如永久不会凌驾 10 个,那上面的代码运转起来就没有题目。但假如用户输入待办事项的数目没有上限,那你就得换一个更高效的处理方案。
假如运用有上百个事宜监听器,更高效的处理方案是给最外层的容器增加一个事宜监听器,当用户真正点击的时刻再去猎取现实被点击的代办事项。这被称为事宜代办,这比给每一个代办事项都零丁增加事宜监听器更高效。
下面是事宜代办的代码:
document.addEventListener('DOMContentLoaded', function() {
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: 在轮回中运用闭包
口试中经常会问到闭包,由于口试官能经由过程这个题目的回复推断你对言语的熟习水平,以及考核你是不是晓得什么时刻运用闭包。
闭包就是能接见作用域外部变量的内部函数 。闭包能用来完成私有化和建立工场函数等作用。关于闭包的罕见口试题是如许的:
写一个函数,轮回一个整数数组,耽误 3 秒打印这个数组中每一个元素的索引。
这个题目罕见(不准确)的完成是如许:
const arr = [10, 12, 15, 21];for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
console.log('The index of this number is: ' + 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('The index of this number is: ' + 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('The index of this number is: ' + i);
}, 3000);
}
题目 #3: Debouncing(防抖动)
有些浏览器事宜能在很短的时候内被触发屡次,比方调解窗口大小或转动页面。假如你给窗口转动事宜增加一个事宜监听器,然后用户不停地疾速向下转动页面,那你的事宜能够在 3 秒以内被触发数千次。这会致使异常严峻的机能题目。
假如在口试中讨论到构建运用程序,以及转动事宜,窗口调解事宜,或许键盘事宜等,请务必说起 debouncing 或许 throttling,作为进步页面速率与机能的要领。来一个 css-tricks 的实例:
2011 年,Twitter 出了一个题目:当转动 Twitter 择要时,页面变的很卡以至无相应。John Resig 写了一篇关于这个题目的博客,诠释了直接将耗时的函数绑定在 scroll 事宜上是一个何等蹩脚的主意。
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('You are scrolling!');
}
// 在 debounce 中包装我们的函数,过 2 秒触发一次
let elem = document.getElementById('container');
elem.addEventListener('scroll', debounce(foo, 2000));
Throttling 是与 debouncing 相似的一种手艺,但它不是在挪用函数之前守候一段时候,throttling 是在较长的时候距离内挪用函数。所以假如一个事宜每 100 毫秒被触发 10 次,throttling 会在每隔 2 秒时实行一次这个函数,而不是在 100 毫秒内实行 10 次事宜。