avaScript技术面试时要小心的三个问题
JavaScript是所有现代浏览器的官方语言。同样的,JavaScript面试题出现在各种各样的面试中。
这篇文章不是讲述JavaScript最新的库、日常的开发实践,或是ES6的新功能。当然了,上面说的这3点经常出现在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个元素,没问题,但是如果有10000个待办事项呢(程序可能还有其他事情要做)?接下来你会创建10000个事件监听函数绑定要每个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: 在循环内使用闭包
闭包问题常常在面试中被提出,面试官能通过它估算出你对JavaScript的熟悉程度,同时了解你对闭包是否熟悉。
闭包的精髓就是:在外部函数中可以读取到内部函数的作用域。闭包可以做这些事:创建私有变量、创建私有函数等。大多数关于闭包的面试题像这样:
循环一个数组,并在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,最终在i为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秒内被触发几千次。这可能会导致很严重的性能问题。
如果你们在面试中讨论构建一个应用,谈到类似滚动、改变窗口尺寸或键盘按下的事件时,一定会提及函数防抖、函数节流(Throttling)去优化页面速度和性能。一个真实的案例,来自guest post on css-tricks:
在2011年,一个问题在Twitter上被提出:当你滚动Twitter feed时,它会十分缓慢且迟钝。John Resig就这个问题发布了一篇博客,它解释了直接绑定函数到滚动事件上是多么糟糕和昂贵的事。
函数防抖是解决这个问题的一种方式,通过限制函数被调用的次数。一个正确实现函数防抖的方法是:把多个函数放在一个函数里调用,隔一定时间执行一次。这里有一个使用原生JavaScript实现的例子,用到了作用域、闭包、this和定时时间:
// debounce函数用来包裹我们的事件
function debounce(fn, delay) {
// 持久化一个timer
let timer = null;
// 闭包可以获取到timer
return function() {
// 通过函数获取到作用域和参数列表
// 通过 'this' 和 'arguments'
let context = this;
let args = arguments;
// 如果事件被触发,清除timer并重新开始计时
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
}
当这个函数绑定在一个事件上,只有经过一段指定的时间后才会被调用。
你可以像这样去使用这个函数:
// 当用户滚动时函数会被调用
function foo() {
console.log('You are scrolling!');
}
// 在事件触发的两秒后,我们包裹在debounce中的函数才会被触发
let elem = document.getElementById('container');
elem.addEventListener('scroll', debounce(foo, 2000));
函数节流是另一个类似函数防抖的技巧,除了使用等待一段时间再调用函数的方法,函数节流还限制固定时间内只能调用一次。所以一个事件如果在100毫秒内发生10次,函数节流会每2秒调用一次函数,而不是100毫秒内全部调用。
想了解更多关于函数防抖和函数节流的信息,下面的文章和教程可能会帮到你:
译者注:之前听朋友讲过这个例子,我就很清晰的分辨了两者的区别:
想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应。假设电梯有两种运行策略 throttle 和 debounce ,超时设定为15秒,不考虑容量限制。
throttle 策略的电梯。保证如果电梯第一个人进来后,15秒后准时运送一次,不等待。如果没有人,则待机。
debounce 策略的电梯。如果电梯里有人进来,等待15秒。如果又人进来,15秒等待重新计时,直到15秒超时,开始运送。
本文由Rockjins Blog翻译,转载请与译者联系。否则将追究法律责任。
avaScript技术面试时要小心的三个问题的更多相关文章
- 面试时,当你有权提问时,别客气,这是个逆转的好机会(内容摘自Java Web轻量级开发面试教程)
前些天,我在博客园里写了篇文章,如何在面试中介绍自己的项目经验,收获了2千多个点击,这无疑鼓舞了我继续分享的热情,今天我来分享另外一个面试中的甚至可以帮助大家逆转的技巧,本文来是从 java web轻 ...
- 十大面试问题解惑,秒杀一切HR、技术面试
最能体现求职者能力的就是面试,能不能拿到Offer,取决于你面试时的表现,只有有准备才能在面试过程中游刃有余.小编收集了10个面试官最爱提的问题,虽然题目千变万化,但是万变不离其宗,只要掌握了答题的技 ...
- java技术面试之面试题大全
转载自:http://blog.csdn.net/lijizhi19950123/article/details/77679489 Java 面试知识点总结 本篇文章会对面试中常遇到的Java技术点进 ...
- 面试时,问哪些问题能试出一个 Android 应用开发者真正的水平?【转自知乎】
这几年面过的各种Android开发也有三位数了,failed的不敢说,pass的基本都没有看走眼,来得晚了也想说说我的体会. 一般面试时间短则30分钟,多则1个小时,这么点时间要全面考察一个人难度很大 ...
- 面试时,问哪些问题能试出一个Android应用开发者真正的水平?
一般面试时间短则30分钟,多则1个小时,这么点时间要全面考察一个人难度很大,需要一些技巧,这里我不局限于回答题主的问题,而是分享一下我个人关于如何做好Android技术面试的一些经验: 面试前的准备 ...
- Amazon前技术副总裁解剖完美技术面试
Amazon前技术副总裁解剖完美技术面试 投递人 itwriter 发布于 2014-03-03 14:30 评论(0) 有1729人阅读 原文链接 [收藏] « » 英文原文:The Anat ...
- (Java后端 Java web)面试时如何展示自己非技术方面的能力(其实就是综合能力)
这篇文章的适用范围其实不仅限于Java后端或Java Web,不过其中有些是拿这方面举例的,在其它方面,大家可以举一反三,应该也能得到些启示. 我们在面试时,会发现有些候选人技术不错,比如在Java ...
- 以技术面试官的经验分享毕业生和初级程序员通过面试的技巧(Java后端方向)
本来想分享毕业生和初级程序员如何进大公司的经验,但后来一想,人各有志,有程序员或许想进成长型或创业型公司或其它类型的公司,所以就干脆来分享些提升技能和通过面试的技巧,技巧我讲,公司你选,两厢便利. 毕 ...
- 95%的技术面试必考的JVM知识点都在这,另附加分思路!
概述:知识点汇总 jvm的知识点汇总共6个大方向:内存模型.类加载机制.GC垃圾回收是比较重点的内容.性能调优部分偏重实际应用,重点突出实践能力.编译器优化和执行模式部分偏重理论基础,主要掌握知识点. ...
随机推荐
- Jade模板引擎学习(二)语法:代码、变量、循环、过滤器及mixin
Jade语法 一.代码 不会被缓冲代码 ul - for(var i=0; i; i++) li Jade Engine 会转换为: <ul> <li>Jade Engine& ...
- C++ 指针常见用法小结
1. 概论 2.指针基础 3. 指针进阶 4. 一维数组的定义与初始化 5. 指针和数组 6. 指针运算 7. 多维数组和指针 8. 指针形参 9. 数组形参 10. 返回指针和数组 11. 结语 ...
- 【HDU】2222 Keywords Search
[算法]AC自动机 [题解]本题注意题意是多少关键字能匹配而不是能匹配多少次,以及可能有重复单词. 询问时AC自动机与KMP最大的区别是因为建立了trie,所以对于目标串T与自动机串是否匹配只需要直接 ...
- 正则表达式实现将html文本转换为纯文本格式(将html字符串转换为纯文本方法)
Regex regex = new Regex("<.+?>", RegexOptions.IgnoreCase); string strOutput = regex. ...
- 所有和Java中代理有关的知识点都在这了。
对于每一个Java开发来说,代理这个词或多或少都会听说过.你可能听到过的有代理模式.动态代理.反向代理等.那么,到底什么是代理,这么多代理又有什么区别呢.本文就来简要分析一下. 代理技术,其实不只是J ...
- 【洛谷 P2756】 飞行员配对方案问题(二分图匹配,最大流)
题目链接 这不是裸的二分图匹配吗? 而且匈牙利算法自带记录方案.. 但既然是网络流24题,那就用网络流来做吧. 具体就是从源点向左边每个点连一条流量为1的边,两边正常连边,流量都是一,右边所有点向汇点 ...
- (Git 钩子)自定义你的工作流 和引用日志
Git 钩子是在 Git 仓库中特定事件发生时自动运行的脚本.它可以让你自定义 Git 内部的行为,在开发周期中的关键点触发自定义的行为. Git 钩子最常见的使用场景包括推行提交规范,根据仓库状态改 ...
- kaggle比赛之悟
一.模型与特征哪个重要? 参与Sberbank Russian Housing Market比赛,一开始使用sklearn的岭回归函数Ridge(),残差值一直是0.37左右,然后同样的特征又使用了X ...
- 利用procdump+Mimikatz 绕过杀软获取Windows明文密码
思路: 就是通过系统自带的procdump去下载存储用户名密码的文件(应该不能那么说这个文件,但是这样理解没问题),然后用猕猴桃读取. procdump.exe Procdump是一个轻量级的Sysi ...
- linux irq 自动探测
前言 编写驱动的时候,经常会用到中断,这时候我们在驱动初始化时就得申请中断,那么问题来了,中断号是多少呢?以前的中断号在板级相关的头文件里面已经静态定义好了,bsp的代码在内核启动过程也会根据那个帮我 ...