• JavaScript面试题总结系列(三)


    3. JavaScript数组

    3.1 数组常用方法

    • map: 遍历数组,返回回调函数返回值组成的新数组,不改变原数组
    • forEach:无法break,可以用try/catch中throw new Error来停止
    • filter:过滤
    • some:有一项返回true,则整体为true
    • every:有一项返回false,则整体为false
    • join:通过指定连接符生成字符串
    • push / pop:末尾推入和弹出,改变原数组, 返回推入/弹出项
    • unshift / shift:头部推入和弹出,改变原数组,返回操作项
    • sort(fn) / reverse:排序与反转,改变原数组
    • concat:连接数组,不影响原数组, 浅拷贝
    • slice(start, end):返回截断后的新数组,不改变原数组
    • splice(start, number, value):返回删除元素组成的数组,value为插入项,改变原数组
    • indexOf / lastIndexOf(value, fromIndex):查找数组项,返回对应的下标
    • reduce / reduceRight(fn(prev, cur), defaultPrev):两两执行,prev 为上次化简函数的return值,cur为当前值(从第二项开始)

    3.2 判断数组

    • instanceof 方法
      • instanceof 运算符是用来判断一个对象的原型链中是不是能找到类型的 prototype
      var arr = [];
      arr instanceof Array; // true
      
    • constructor 方法

      constructor属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数

      var arr = [];
      arr.constructor == Array; // true
      
    • isArray() 方法
      var a = new Array(123);
      var b = new Date();
      console.log(Array.isArray(a)); // true
      console.log(Array.isArray(b)); // false
      
    • Object.prototype.toString.call()

      这个在之前讲判断数据类型的文章里说过,这里不再赘述。

    3.3 数组的遍历

    • map和forEach的区别
      • map具有返回值,返回一个新的数组,不修改原数组;
        forEach没有返回值,直接修改原数组
      • 从性能上来说,forEach的性能要略好于map。
        测试例子请狠狠点击这里
    • JavaScript数组和对象的遍历方式,以及几种方式的比较

      通常我们会用循环的方式来遍历数组。但是循环是 导致js 性能问题的原因之一。一般我们会采用下几种方式来进行数组的遍历

      • for in循环
      • for循环
      • forEach
        • 这里的 forEach回调中两个参数分别为 value,index
        • forEach 无法遍历对象
        • IE不支持该方法;Firefox 和 chrome 支持
        • forEach 无法使用 break,continue 跳出循环,且使用 return 是跳过本次循环
      • 这两种方法应该非常常见且使用很频繁。但实际上,这两种方法都存在性能问题
      • 在方式一中,for-in需要分析出array的每个属性,这个操作性能开销很大。用在 key 已知的数组上是非常不划算的。所以尽量不要用for-in,除非你不清楚要处理哪些属性,例如 JSON对象这样的情况
      • 在方式2中,循环每进行一次,就要检查一下数组长度。读取属性(数组长度)要比读局部变量慢,尤其是当 array 里存放的都是 DOM 元素,因为每次读取都会扫描一遍页面上的选择器相关元素,速度会大大降低
      • ES6新增的 for of 循环。for in循环通常用来遍历对象的Key,for of通常用来遍历对象的Value。

    3.4 数组去重

    • 利用双重循环去判断。声明一个空数组,然后遍历原数组,从原数组第一个元素开始往新的数组中放,如果没有该值,则push进去,否则跳过,最后返回新数组。实现数组去重。
    • 使用ES的Set集合。
      Set集合的特性之一是其集合中没有重复的元素,因此可以利用这一特性来实现数组去重的目的。举例:
    var array2 = [...new Set([1,2,3,3,3,4,5])];
    console.log(array2); // Array(5) [ 1, 2, 3, 4, 5 ]
    

    3.5 数组乱序

    • 思路:使用sort()排序,或者使用洗牌算法。
    • 实现:
      • 创建一个数组
      let arr = Array(100000).fill(0).map((item, index) => index + 1);
      
        1. 直接利用sort进行排序,有漏洞,大部分元素位置没有移动
      arr.sort((a, b) => (Math.random() > 0.5 ? -1 : 1));
      console.log(arr);
      
        1. 经典洗牌算法实现
      function shuffle(array) { 
          let arrayLength = array.length,   
              randomIndex, //随机数   
              tempItem; //临时存储元素  
          for (let i = arrayLength - 1; i >= 0; i--) {    
              randomIndex = Math.floor(Math.random() * (i + 1));    
              tempItem = array[randomIndex];    
              array[randomIndex] = array[i];    
              array[i] = tempItem;  
          }  
          return array;
      }
      console.log(shuffle(arr));
      

    3.6 数组的扁平化(数组降维/多维转一维)

    3.6.1 概念

    数组的扁平化是指将一个多为数组变为一维数组。例如:

    [1, [2, 3, [4, 5]]] ------> [1, 2, 3, 4, 5]

    3.6.2 实现

    • ES10 数组新特性: Array.prototype.flat()方法

      flat()方法按照一个可以指定的嵌套深度的参数来递归遍历数组,并将所有元素以及遍历到的子数组里面的元素合并返回一个新数组。

      var arr = [true, function(){}, [{}, [2]]];
      var newArr = arr.flat(2);
      console.log(newArr); //  [true, ƒ, {…}, 2]
      
    • 递归。如下:
      function flatten(arr) {
          var res = [];
          arr.map(item => {
              if(Array.isArray(item)) {
                  res = res.concat(flatten(item));
              } else {
                  res.push(item);
              }
          });
          return res;
      }
      
    • 扩展运算符
      function flatten(arr) {
          while(arr.some(item=>Array.isArray(item))) {
              arr = [].concat(...arr);
          }
          return arr;
      }
      
    • reduce

      使用数组的reduce方法,遍历数组中的每一个项,如果某一项是数组,则继续遍历,否则concat(连接数组);
      举例:

      function flatten(arr) {  
          return arr.reduce((result, item)=> {
              return result.concat(Array.isArray(item) ? flatten(item) : item);
          }, []);
      }
      var arr = [false, function(){}, [{}, [2]]];
      var arr2 = [1, [2,3],4,[5,[6,7]]];
      var newArr = flatten(arr); 
      var newArr2 = flatten(arr2);
      console.log(newArr); // [false, ƒ, {…}, 2]
      console.log(newArr2); // [1, 2, 3, 4, 5, 6, 7]
      

    3.6.3 总结

    实现数组扁平化的方法有很多,但是最核心的一点就是,遍历数组,拿到数组的每一项,如果是数组,再继续遍历,直到每一项不再是数组则停止。然后将这些项放到一个新的数组,最后将这个数组返回。数组降维,或者多维转一维都和数组扁平化是一个道理。


    参考链接:
    http://blog.poetries.top/FE-Interview-Questions/review/#_23-%E6%95%B0%E7%BB%84-array
    https://www.cnblogs.com/chris-oil/p/8743509.html
    https://www.cnblogs.com/owenzh/p/11058708.html https://juejin.im/post/5d391d336fb9a07ebe750343https://juejin.im/post/59716f15f265da6c4c500fc7
    https://juejin.im/post/5adc8e396fb9a07aa0479725 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat

  • 相关阅读:
    KM匹配模板
    BestCoder 1st Anniversary 1002-1005
    SGU 106 The equation
    sgu 104 Little shop of flowers
    SGU Magic Pairs
    关于 “'sqlite3' 不是内部或外部命令.....”问题
    通过django 速成 blog
    windows 通过appache链接cgi程序
    A Lot of Games(Trie树 + 博弈)
    树的点分治 (poj 1741, 1655(树形dp))
  • 原文地址:https://www.cnblogs.com/zxxsteven/p/11725505.html
Copyright © 2020-2023  润新知