JavaScript 中 你需要知道的有关于数组的详细知识点

388 阅读3分钟

JavaScript 中你需要知道的有关于数组的详细知识点

1、ES6 新增数组方法

Array.from()Array.of()copyWithin()find()findIndex()fill()entries()keys()values()includes()

2、ES5 新增数组方法

forEach()map()filter()some()every()indexOf()lastIndexOf()reduce()reduceRight()

3、数组的这些方法,哪些能改变原数组?

copyWithin()fill()pop()push()reverse()shift()sort()splice()

4、someevery 有什么区别?

从中文含义能看出来,some 是某些,every 是每一个,它们都返回一个 Boolean 值。

5、数组里面有 10 万条数据,取第一个元素和第 10 万个元素哪个用时长?

用时基本上一样,因为 js 里面没有数组类型,数组其实也是一个对象,keyvalue

6、数组去重你有几种方法?

1. 多层循环遍历法

  • 双重 for 循环;
  • 递归循环。

2. 利用语法自身键不可重复性或者API去重

  • ES6 Set 去重;
  • 新建空对象去重;
  • 单层循环 + filter/includes/indexOf
  • 单层循环 + MapObject 去重。

7、for 循环和 forEach 的性能哪个更好一点?

for 循环的性能更好

  • for 循环没有任何额外的函数调用栈和上下文;
  • forEach 不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能。

8、sort 排序是按照什么方式来排序的?

默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的。

9、多维数组转为一维数组

  • reduce 递归实现
  • joinsplit 实现
  • 递归遍历
  • flat 方法
  • toStringsplit 实现
  • 广度优先遍历/深度优先遍历

10、广度优先遍历和深度优先遍历如何实现

JS深度优先遍历和广度优先遍历

1. 深度优先遍历

  • 访问顶点 v
  • 依次从 v 的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和 v 有路径相通的顶点都被访问;
  • 若此时途中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到所有顶点均被访问过为止。
const depth = (node) => {
    let stack = []
    let nodes = []
    if (node) {
        stack.push(node)
        while (stack.length) {
            //每次取最后一个
            let item = stack.pop()
            let children = item.children || []
            nodes.push(item)
            //判断children的长度
            for (let i = children.length - 1; i >= 0; i--) {
                stack.push(children[i])
            }
        }
    }
    return nodes
}

2. 广度优先遍历

  • 创建一个队列,并将开始节点放入队列中;
  • 若队列非空,则从队列中取出第一个节点,并检测它是否为目标节点;
  • 若是目标节点,则结束搜寻,并返回结果;
  • 若不是,则将它所有没有被检测过的字节点都加入队列中;
  • 若队列为空,表示图中并没有目标节点,则结束遍历。
const breadth = (node) => {
    let nodes = []
    let stack = []
    if (node) {
        stack.push(node)
        while (stack.length) {
            //取第一个
            let item = stack.shift()
            let children = item.children || []
            nodes.push(item)
            for (let i = 0; i < children.length; i++) {
                stack.push(children[i])
            }
        }
    }
    return nodes
}

11、实现一个 reduce

Array.prototype.myReduce = function (fn, init) {
    if (!init && this.length === 0) { // 如果数组长度为0
        return this
    }
    let start = 1, pre = this[0]; // 从数组第二个开始下标为1
    if (init !== undefined) { // 如果 init 字段存在,从第一个开始,下标为 0
        start = 0;
        pre = init;
    }
    for (let i = start; i < this.length; i++) { // 循环
        let current = this[i]
        pre = fn.call(this, pre, current, i, this) // 把每次的 reduce 的值返回
    }
    return pre
}

12、实现一个数组随机打乱的算法

function disOrder2 (arr) {
    for (let i = 0; i < arr.length; i++) { // 遍历
        const randomIndex = Math.floor(Math.random() * ary.length) // 生成随机数
        swap(arr, i, randomIndex)
    }
}
function swap(arr, i, _i) { // 交换
    const tem = arr[i]
    arr[i] = arr[_i]
    arr[_i] = tem  
}
arr = [1,2,3,4,5,6,7,8]
disOrder(arr)
console.log(arr)

13、给一串数字增加逗号分隔

1. 正则

num.replace(/(\d)(?=(\d{3})+(\.|$))/g, "$1,")

2. 遍历

function formatNumber(num) {
  if (!num) return "";
  let [int, float] = num.split(".");
  let intArr = int.split("");
  let result = [];
  let i = 0;
  while (intArr.length) {
    if (i !== 0 && i % 3 === 0) {
      result.unshift(intArr.pop() + ",");
    } else {
      result.unshift(intArr.pop());
    }
    i++;
  }
  return result.join("") + "." + (float ? float : "");
}

14、mapfindeverysomeforEach 等方法的第二个参数是干什么的?

arr.every(callback(element[, index[, array]])[, thisArg])
  • thisArg 执行 callback 时使用的 this 值。