JavaScriptlv面试需要注意什么么

几个常见js面试问题整理
1.关于&+&和&-&中出现number类型时的转换
var a = '' + 3;
//尝试将3转化为字符串
var b = 4;
console.log(typeof a);
console.log(a+b);
console.log(a-b);
//尝试将字符串转化为number
var foo = &11&+2+&1&; //体会加一个字符串'1' 和 减去一个字符串'1'的不同
console.log(foo);
console.log(typeof foo);
2.js数组去重的问题
很容易想到的办法
var arrayNum = [0, 0, 0, 1, 1, 3, 3, 4, 5, 6, 7];
var arr = new Array();
uniqArray = function (array) {
var newArray = [];
for (var i = 0; i & array. i++) {
if (newArray.length != 0) {
for (var m = 0; m & newArray. m++) {
var repeatNum =
if (array[i] == newArray[m]) {
repeatNum =
if (repeatNum == false) {
newArray.push(array[i]);
newArray.push(array[i]);
return newA
时间复杂度是O(n^2)
优化后的代码:
var arrayNum = [0, 0, 0, 1, 1, 3, 3, 4, 5, 6, 7];
var testArray = function(arry) {
var tempArray = [];
for (var i = 0, l = arry. i & i++) {
//使用数组的indexof方法来判断是否在temparray中找到当前元素的索引
if (tempArray.indexOf(arry[i])===-1 && arry != ''){
tempArray.push(arry[i]);
return tempA
console.log(testArray(arrayNum));
这时的时间复杂度是O(n)
3.js对象的简单使用
在js中没有class这样的关键字来声明对象,仅仅是通过function变量名首字母大写的方式,来与js函数做区别(js函数采用驼峰命名法)
function DongJia(ver){
var defaultValue = 0.01;
this.version = ver ? ver : defaultV
this.getVersion = function(){
return this.
this.setVersion = function(ver){
this.version =
var dongjia = new DongJia();
//没有默认值
console.log(dongjia.getVersion());
//使用set函数改变默认值
dongjia.setVersion(0.02);
console.log(dongjia.getVersion());
//有默认值,直接给version赋值
var dongjia2 = new DongJia(0.02);
console.log(dongjia2.getVersion());
4.js中对数组的clone
使用jquery进行对象的复制
jQuery.extend( [ deep ], target , object1 [, objectN... ] )
请根据前面语法部分所定义的参数名称查找对应的参数。
deep 可选/Boolean类型指示是否深度合并对象,默认为false。如果该值为true,且多个对象的某个同名属性也都是对象,则该&属性对象&的属性也将进行合并。
target Object类型目标对象,其他对象的成员属性将被复制到该对象上。 object1 可选/Object类型第一个被合并的对象。
objectN 可选/Object类型第N个被合并的对象。
示例代码:
var a = { k1: 1, k2: 2, k3: 3 };
var b = {k4:4, k5:5};
c=$.extend(a);
//将a对象复制到jquery对象上,并赋值给c
console.log('------------');
console.log(c === $);
//c对象指向的是$对象,所以结果true
console.log(a === $);
console.log('------c------');
console.log(c.k2);
//相当于$.k2
console.log('------c------');
console.log(c);
//c.k2 = 777;
console.log('------a------');
console.log(a);
console.log('------b------');
console.log(b);
console.log('------$------');
console.log($);
console.log($.k2);
看下面的一段代码:vcD4NCjxwcmUgY2xhc3M9"brush:">
var d = $.extend({}, a)
console.log(d);
d.k2 = 3456;
console.log(d);
console.log(a);
可以知道,jquery中extend()不是复制引用,而是创建了新的对象
注意事项:
该函数复制的对象属性包括方法在内。此外,还会复制对象继承自原型中的属性(JS内置的对象除外)。
参数deep的默认值为false,你可以为该参数明确指定true值,但不能明确指定false值。简而言之,第一个参数不能为false值。
如果参数为null或undefined,则该参数将被忽略。
如果只为$.extend()指定了一个参数,则意味着参数target被省略。此时,target就是jQuery对象本身。通过这种方式,我们可以为全局对象jQuery添加新的函数。
如果多个对象具有相同的属性,则后者会覆盖前者的属性值。
看下面一段代码对数组对象进行拷贝:
var test = [1,2,34,];
console.log(test);
var contest= $.extend([],test);
console.log(contest);
contest.push(567);
console.log(test);
console.log(contest);
5.js闭包场景的使用
场景的使用是当我点击li标签的时候,移除当前li标签,并且将li标签中的内容添加到下方的p标签中
完整的代码整理如下:
&script type="text/javascript"&
$(function() {
var $liObj = $('li'),
for (var i = 0, l = $liObj. i < i++) {
(function(i) {
$liObj.eq(i).on('click', function() {
conText = $('#content').text();
$('#content').html(conText + $liObj.eq(i).text());
$liObj.eq(i).remove();
经过测试可以实现所需要的功能。废话不说,直接上题。
slice(),接收两个参数,第一个为开始index(从0开始),第二个为结束的index(也是从0开始,但是不包括index本身,只到index-1)。返回值是截取的数组,原数组不变化。传第三个参数,没有作用。
splice(),接收无数个参数,第一个为开始的index(从0开始),第二个为删除的元素的个数(0代表不删除,1代表删除一个...),第三个为添加的元素,第四个也为添加的元素.....,返回值是删除的元素组成的数组,如果删除了0个就返回空数组,原数组会被改变成被操作后的数组(这里需要注意一个问题,比如:arr =[1,2,3],arr.splice(1,0,4),arr会变成[1,4,2,3],添加的4是在2的前面插入)。
以上两个方法的区别和应用,面试官会问。
forEach方法(除了数组对象之外,forEach&方法可由具有&length&属性且具有已按数字编制索引的属性名的任何对象使用。比如:{0:"a",1:"b",length:2})
arr.forEach(callback,thisArg),只接受两个参数,一个是回调方法,一个是context.callback必选,&最多可以接受三个参数的函数。&
回调函数的语法如下所示:
function callback(value, index, array1),value:数组元素的值。index:数组元素的数字索引。array1:包含该元素的数组对象。可以在回调方法中改变原数组。
这个方法的作用就是:利用数组中的值做一些应用,比如:显示出来,累加等等。
这里大家可以去区分一下$("div"),jQuery对象的each方法。很像,但是在回调方法调用时,传参不一样,请仔细查看。
链接地址:/chaojidan/p/4141413.html
map方法,跟forEach方法差不多,唯一的区别是,arr.map(callback,thisArg),有返回值,返回值是:对每个数组中的元素执行callback后,callback返回的值组成的数组。
当然原数组也不会改变,除非你在callback(value, index, array1)中直接改变array1。
这个方法的作用就是:把数组组装成其他的形式,比如:对数组中的每一项加1,或者平方等等。
这里大家可以去区分下$("div"),jQuery对象的map方法,也很像,但是传参不一样,同时,回调方法调用时,传参也不一样。请仔细查看。
链接地址:/chaojidan/p/4141413.html
indexOf方法:接收两个参数:searchElement:必需。 要在 array1 中定位的值。fromIndex:可选。 用于开始搜索的数组索引, 如果省略 fromIndex,则从索引 0 处开始搜索。&如果&fromIndex&大于或等于数组长度,则返回 -1。&
lastIndexOf:接收两个参数:searchElement:必需。 要在 array1 中定位的值。fromIndex:可选。&
&最后就是一个很重要的方法,面试经常问到的方法:
replace方法:它会跟正则一起出题。它接收两个参数,比如:str.replace(str1,str2);
str1必需。规定子字符串或要替换的模式的 RegExp 对象。请注意,如果该值是一个字符串,则只会替换一个。比如:"abbc".replace("b","d") &-& 返回"adbc"。
str2必需。规定了替换文本或生成替换文本的函数。
返回值,就是替换之后的字符串。原字符串不改变。
如果需要把匹配到的字符全部替换,需要使用正则"abbc".replace(/b/g,"d") &&-& 返回"addc"。
replace() 方法的参数 str2可以是函数。在这种情况下,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 str中出现的位置。最后一个参数是 str本身。
比如:"abcd".replace(/(a)(b)(c)/g,function(match,$1,$2,$3,index,str){  match:abc(匹配到的字符串),$1:a(匹配到的第一个子表达式),以此类推,如果没有子表达式,就不会有这些参数,就直接是index。  index:0(匹配到的字符串在原始字符串中的位置,也就是"abc"在"abcd"中的位置),最后一个是str:"abcd"(原始字符串)})
此方法功能很强大,推荐精读,有时可以让面试官眼前一亮。
加油!原文链接:
阅读排行榜2012年10月 Java大版内专家分月排行榜第三2012年6月 Java大版内专家分月排行榜第三
2013年10月 Java大版内专家分月排行榜第二2013年3月 Java大版内专家分月排行榜第二2013年2月 Java大版内专家分月排行榜第二
2013年7月 Java大版内专家分月排行榜第三2013年5月 Java大版内专家分月排行榜第三2013年4月 Java大版内专家分月排行榜第三
2012年3月 Java大版内专家分月排行榜第三
2013年10月 Java大版内专家分月排行榜第二2013年3月 Java大版内专家分月排行榜第二2013年2月 Java大版内专家分月排行榜第二
2013年7月 Java大版内专家分月排行榜第三2013年5月 Java大版内专家分月排行榜第三2013年4月 Java大版内专家分月排行榜第三
2013年10月 Java大版内专家分月排行榜第二2013年3月 Java大版内专家分月排行榜第二2013年2月 Java大版内专家分月排行榜第二
2013年7月 Java大版内专家分月排行榜第三2013年5月 Java大版内专家分月排行榜第三2013年4月 Java大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。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. 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 关键字,它会在函数调用时创建一个新的绑定
&// 了解更多:/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 次事件。
更多关于 debouncing 和 throttling 的信息请参考以下文章和教程:
JavaScript 中的 Throttling 和 Debouncing
Throttling 与 Debouncing 的区别
实例解析 Throttling 和 Debouncing
Throttling 函数调用 —— Remy Sharp
阅读(...) 评论()}

我要回帖

更多关于 面试需要注意些什么 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信