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中对于对象的赋值,经常听到深拷贝和浅拷贝,浅拷贝就是直接对象赋值共同使用一个引用地址,但大多时候我们并不希望这样,而是希望对象之间能够完全独立,这个时候就需要深度克隆了,基本原理是对对象的所有属性进行遍历复制。

原文地址:https://www.cnblogs.com/webLilingyun/p/5515334.html