这段时间我也面了几次,也看了数不胜数的面经,然而面经也只能起到辅助的作用(在看的时候难免会出现眼高手低的情况),我就栽了几次了?,所以建议大家在准备的时候一定要多动手联系啊。。。
我准备了几道高频题(我自己经历),我会分几次博客来分享…
数组去重
这道题我遇到过几次吧算是,之前老是和数组深拷贝弄混淆,我要记录下来。
1、ES6的Set()
//set可以去掉字符串、数值、布尔、undefined、null、NaN
//es6中Set内部利用算法 “Same-value-zero equality”,类似于“===”,不同的是NaN===NaN =>true
let arr = [1,2,5,6,51,4,21,1,2];
let set = new Set(arr);
console.log(Array.from(set)); //[1, 2, 5, 6, 51, 4, 21]
2、利用indexOf+新数组
function unique(arr){
let res = [];
res[0] = arr[0];
for(let i = 1;i<arr.length;i++){
if(res.indexOf(arr[i])==-1){
res.push(arr[i])
}
}
return res;
}
let arr = [1,'1',4,null,null,'1',4,undefined,undefined];
console.log(unique(arr)) //[1, "1", 4, null, undefined] 不能去掉NaN
3、利用对象键值不重复(不推荐)
function unique(arr){
let res = [];
let obj = {};
for(let i = 0;i<arr.length;i++){
if(!obj[arr[i]]){ //漏洞
obj[arr[i]] = true;
res.push(arr[i])
}
}
return res;
}
let arr = [1,2,3,'1','2','3'] //[1,2,3]
// let arr = [1,'1',4,null,null,'1',4,undefined,undefined,NaN,NaN];
console.log(unique(arr))
不推荐的原因:经过我的测试发现,if(!obj[arr[i]]){}判断的时候,会把字符串和数值当成同一种键存到对象里面,这种方法无法判断字符串和数值(知道解决方法的留言哦?)
4、终极版本
function unique(arr) {
const result = [];
result[0] = arr[0];
for (let i = 1; i < arr.length; i++) {
if (isAdd(result, arr[i])) { result.push(arr[i]) }
}
return result;
}
function isAdd(result, val) { //判断是否可以添加到新数组中
for (let value of result) { //遍历新数组
if (isEqual(value, val)) return false;
}
return true;
}
function isEqual(val1, val2) { //判断当前元素是否存在与新数组中
let type1 = typeof val1;
let type2 = typeof val2;
if (type1 !== type2) return false;
if (type1 !== 'object') return val1 === val2;
for (let key of Object.keys(val1)) { //判断数组和对象类型
if (!val2[key]) return false;
if(!isEqual(val1[key], val2[key])) return false; //递归调用去判断子元素
}
return true;
}
let arr = [1,'1',4,{"a":1},{"a":1},[1],[1],undefined,NaN,NaN];
console.log(unique(arr)) //[1, "1", 4, {…}, Array(1), undefined, NaN, NaN]
一、NaN!==NaN;typeof NaN ‘number’,如果想判断NaNNaN可以使用Number.isNaN(),使用这个方法会判断NaN是否相等(不包括字符串)
二、存在null时候会报错,因为typeof null == ‘object’,进行判断的时候不符合上面的条件,最后条件判断的时候就会出错。
事件委托
也称为事件代理,将事件绑定到目标元素的父元素上,利用事件冒泡机制,给父元素监听事件,通过event.target来判断目标元素。这样做的好处既可以减少事件的注册数量、节约内存空间,还可以让新加的元素拥有方法。
简约版本
<ul id="ul">
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
//js
var ul = document.getElementById('ul');
ul.addEventListener('click',function(e){
if(e.target.tagName=='LI'){ //获取的标签都是大写,也可以转小写再判断
console.log(e.target.innerText)
}
},false) //利用冒泡
通过绑定到外层的父元素点击事件,当你点击 ‘li’ 的时候由于冒泡原理,会向上触发,刚好父元素 ul 有点击事件,则触发onclick事件,打印内容。
新加元素也可以拥有事件
ul.addEventListener('click',function(e){
、、、
},false)
//按钮点击添加事件
var lis = ul.getElementsByTagName('li');
var btn = document.getElementById('btn');
btn.onclick = function(){
var li = document.createElement('li');
li.innerText = Number(lis[lis.length-1].innerText)+111; //添加内容
lis.length++;
ul.appendChild(li);
}
今天就先讲这两个题,可以继续关注我的博客哦!?
说几道昨天晚上做腾讯的笔试题,挺难的。
还是关于数组
let arr = [0,1,2,3,4,5,6,7,8,9];
arr.forEach((_,index)=>index%2===0&&arr.splice(index,1));
想想结果…
1、首先要清楚,forEach()这个方法是会改变原数组滴,面试中也会经常问道 map和forEach区别, 理解到了会改变原数组就好理解啦!!!
下标为0:0 % 2 === 0,先删除第一个元素,数组变成[1,2,3,4,5,6,7,8,9]
下标从1开始:1=>2,2=>3,删除第三个元素,数组为[1,2,4,5,6,7,8,9]
下标从3开始:3=>5,4=>6,删除元素,数组为[1,2,4,5,7,8,9]
依次循环,最后数组变为[1,2,4,5,7,8]
2、{}+[] === 0
{}语句优先,被当作空,{}在右边的时候,当作表达式
{}为空,[]调用其valueOf会转为 "",然后转为0,所以结果为0
[]+{} => [object,Object]
有不对的地方欢迎大家指出,我们共同进步。