js笔试题系列之二——数组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js笔试题系列之二——数组相关的知识,希望对你有一定的参考价值。
(1)快速创建一个数组,数组中含有100个值为0元素。
方法一:
var arr = new Array(100); for(var i=0;i<100;i++){ arr[i] = 0; }
方法二:
var arr = new Array(100); arr.join(‘0‘).split(‘‘); //注意此方法结果0为字符类型
面试官会喜欢哪个答案呢?
(2)经典的数组去重问题
数组去重可以说是各大公司前端笔试中的常见题,以下列出几种典型的解决方法
方法一:传统双循环对比法
function unique0(arr){ var n = []; //一个新的临时数组 for(var i=0,l=arr.length; i<l; i++) //遍历目标数组 { var mark = 1; //标记字段 for(var j=0;j<n.length+1;j++){ //遍历临时数组 if(arr[i] === n[j]){ mark = 0; break; } } mark && n.push(arr[i]); } return n; }
方法二:利用indexof方法
function unique1(arr){ var n = []; //一个新的临时数组 for(var i=0,l=arr.length; i<l; i++){ //遍历当前数组 //如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面 if (n.indexOf(arr[i]) == -1) n.push(arr[i]); } return n; }
方法三:利用对象属性唯一性
function unique2(arr){ var n = []; //存放新数组 var json = {}; //利用对象属性唯一性 for(var i=0,l=arr.length; i<l; i++){ //遍历当前数组 if(!json[arr[i]]){ //判断json中是否有arr[i]属性 n.push(arr[i]); json[arr[i]] = 1; //标记json新属性arr[i] } } return n; }
三种方法都有各自的优缺点,第一种方法利用双循环,所以当数组很大的时候效率是最低的,第二种利用了ES5的indexof方法,如果不考虑低版本IE的话(否则得先实现此方法)比较推荐,最后一种方法其实隐藏着一个BUG:由于这种方法利用的是对象属性唯一性,当给对象属性赋值为数组元素时,数组元素会被转换成字符串类型:unique2([‘1,1‘,[1,1]])执行后返回了错误的结果["1,1"],也就是说此方法在多维数组场景下是不可行的。
(3)删除给定数组的第二项和第三项,再将数组最后一个元素压入数组头部
这里考察了数组操作的常用方法,我们以var arr = [1,2,3,4,5]为初始数组,先来看这个解答结果:
arr.splice(1,2).unshift(arr.pop()); ==>[1, 4]
这种解决方法结果并不是我们期望的,因为按照题目的要求结果应该是[5,1,4],那么是哪里出问题了?原因就是这里不能以这种链式写法,因为splice方法的返回结果并不是原数组了,而是截取的数组片段,所以正确解答只需要这样改:
arr.splice(1,2); arr.unshift(arr.pop()); ==>[5,1,4]
(4)填空题,实现输出[‘c‘,‘d‘]
var data = {a:1,b:2,c:3,d:4}; Object.keys(data).filter(function(x){ return ______; })
首先,你如果对Object.keys或者filter两个ES5新增方法不了解的话,这道题目就很难回答了。如果这两个方法都难不倒你,那你就离成功很近了,因为实际上只需要再下划线直接填写‘x‘,就会返回[‘a‘,‘b‘,‘c‘,‘d‘],那么如何让返回结果为[‘c‘,‘d‘]呢,聪明的你肯定已经想到了就是 x > ‘b‘。‘c‘、‘d‘和字符‘b‘比较结果为true所以能够返回,而‘a‘、‘b‘元素比较为false,不予返回。
(5)代码实现如下要求
var arr = [1,2]; var new_arr; 要求实现: new_arr === arr ==>false new_arr[0] == arr[0]; ==>true new_arr[1] == arr[1]; ==>true
这道题目先要看懂意思,了解出题者意图:题目要求new_arr不能严格等于arr,但是里面的元素是相等的。我们知道实现数组内元素相等很简单,在这里直接new_arr = arr就可以了,但是如果简单赋值则无法满足第一个条件,即两个数组不能严格相等。所以,出题者希望答题者了解的地方在于对对象引用赋值的了解、如何实现对象值传递而不是引用传递两个知识点。关于数组的值传递解决办法很简单,只需要遍历原数组的元素复制过去即可,当然这里不需要我们自己去写个遍历:
var new_arr = arr.slice(); //or var new_arr = arr.concat();
上面两个方法都可以实现题目要求。
(6)随机选取5-105中的10个不重复随机整数,然后按从小到大排序
这里考了两个点,不重复随机数的获得、数字数组的排序,其中数组排列不能够直接用sort(),而必须传一个函数参数,否则将不能得到预期结果,因为数组排序默认是按照字符比较:
方法一:
var arr = []; //存放不重复随机数 var n; while(arr.length < 10){ n = Math.round(5+Math.random()*100); arr.indexOf(n)==-1&&arr.push(n); } arr.sort(function(a,b){return a-b}); console.log(arr);
方法二:
var arr = []; //存放所有可能数 for(var i=0;i<=100;i++){ arr[i] = 5+i; } arr.sort(function(a,b){return 0.5 - Math.random();}).slice(0,10).sort(function(a,b){return a-b});
方法二的思路和方法一明显不同,这里是把所有在范围区间的整数先存放在arr中,然后依次调用——sort(顺序打乱)——slice(取开头10个元素)——sort(按大小排序返回)
(7)如何让所有浏览器兼容ES5的数组forEach方法
Array.prototype.forEach || (Array.prototype.forEach = function(fun) { for (var i = 0; i < this.length; i++) { fun(this[i], i, this); } })
先检测浏览器是否支持forEach,如果不支持则自己去写一个实现相同功能的同名方法,其它类似问题都可以按此思路解决。
(8)深度克隆对象
var cloneObj = function(obj){ var str, newobj = obj.constructor === Array ? [] : {}; if(typeof obj !== ‘object‘){ return obj; } else if(window.JSON){ str = JSON.stringify(obj), //系列化对象 newobj = JSON.parse(str); //还原 } else { for(var i in obj){ newobj[i] = typeof obj[i] === ‘object‘ ? cloneObj(obj[i]) : obj[i]; } } return newobj; };
在js中对于对象的赋值,经常听到深拷贝和浅拷贝,浅拷贝就是直接对象赋值共同使用一个引用地址,但大多时候我们并不希望这样,而是希望对象之间能够完全独立,这个时候就需要深度克隆了,基本原理是对对象的所有属性进行遍历复制。
以上是关于js笔试题系列之二——数组的主要内容,如果未能解决你的问题,请参考以下文章