前端面试题快问快答(4)

92 阅读3分钟

数组去重方法总结

方法一、利用 ES6 Set 去重( ES6 中最常用)

function unique (arr) {
        return Array.from(new Set(arr))
}

const arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefind]
    console.log(unique(arr))
    //[1, "true", true, 15, false, undefined]

方法二、利用 for 嵌套 for ,然后 splice 去重( ES5 中最常用)

function unique(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] == arr[j]) {
        //第一个等同于第二个, splice 方法删除
        arr.splice(j, 1);
        j--;
      }
    }
  }
  return arr;
}
var arr = [
  1,
  1,
  'true',
  'true',
  true,
  true,
  15,
  15,
  false,
  false,
  undefined,
  undefined,
];
console.log(unique(arr));
//[1, "true", 15, false, undefined]

思想:

  • 双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值

方法三、利用 indexOf 去重

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  let array = [];
  for (let i = 0; i < arr.length; i++) {
    if (array.indexOf(arr[i]) === -1) {
      array.push(arr[i]);
    }
  }
  return array;
}

思想:

  • 新建一个空的结果数组, for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则 push 进数组

方法四、利用 sort()

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  arr = arr.sort();
  let arrry = [arr[0]];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] !== arr[i - 1]) {
      arrry.push(arr[i]);
    }
  }
  return arrry;
}

方法五、利用对象的属性不能相同的特点进行去重

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  let arrry = [];
  let obj = {};
  for (let i = 0; i < arr.length; i++) {
    if (!obj[arr[i]]) {
      arrry.push(arr[i]);
      obj[arr[i]] = 1;
    } else {
      obj[arr[i]]++;
    }
  }
  return arrry;
}

方法六、利用 includes

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  var array = [];
  for (var i = 0; i < arr.length; i++) {
    if (!array.includes(arr[i])) { //includes 检测数组是否有某个值
      array.push(arr[i]);
    }
  }
  return array;
}

方法七、利用 hasOwnProperty

function unique(arr) {
  let obj = {};
  return arr.filter(function (item, index, arr) {
    return obj.hasOwnProperty(typeof item + item)
      ? false
      : obj[typeof item + item];
  });
}

方法八、利用 filter

function unique(arr) {
  return arr.filter(function (item, index, arr) {
    // 当前元素,在原始数组中的第一个索引 == 当前索引值,否则返回当前元素
    return arr.indexOf(item, 0) === index;
  });
}

方法九、利用递归去重

function unique(arr) {
  var array = arr;
  var len = array.length;
  array.sort(function (a, b) {
    //排序后更加方便去重
    return a - b;
  });
  function loop(index) {
    if (index >= 1) {
      if (array[index] === array[index - 1]) {
        array.splice(index, 1);
      }
      loop(index - 1); //递归 loop ,然后数组去重
    }
  }
  loop(len - 1);
  return array;
}

方法十、利用 Map 数据结构去重

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array(); //数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if (map.has(arr[i])) {
      //如果有该 key 值
      map.set(arr[i], true);
    } else {
      map.set(arr[i], false);
      array.push(arr[i]);
      //如果没有该 key 值
    }
  }
  return array;
}

思想:创建一个空 Map 数据结构,遍历需要去重的数组,把数组的每一个元素作为key 存到 Map 中。由于 Map 中不会出现相同的 key 值,所以最终得到的就是去重后的结果。

方法十一、利用 reduce+includes

function unique(arr){
  return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[])
  }

方法十二、 [...new Set(arr)]

[...new Set(arr)]
// 代码就是这么少 ---- (其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码

Javascript 全局函数和全局变量?

全局变量

  • Infinity 代表正的无穷大的数值
  • NaN 指示某个值是不是数字值
  • undefined 指示未定义的值

全局函数

  • decodeURI() 解码某个编码的 URI
  • decodeURIComponent() 解码一个编码的 URI 组件
  • encodeURI() 把字符串编码为 URI
  • encodeURIComponent() 把字符串编码为 URI 组件
  • escape() 对字符串进行编码
  • eval() 计算 JavaScript 字符串,并把它作为脚本代码来执行
  • isFinite() 检查某个值是否为有穷大的数
  • isNaN() 检查某个值是否是数字
  • Number() 把对象的值转换为数字
  • parseFloat() 解析一个字符串并返回一个浮点数
  • parseInt() 解析一个字符串并返回一个整数
  • String() 把对象的值转换为字符串
  • unescape() 对由 escape() 编码的字符串进行解码

浏览器缓存?

浏览器缓存分为强缓存和协商缓存。当客户端请求某个资源时,获取缓存的流 程如下:

  • 先根据这个资源的一些 http header 判断它是否命中强缓存,如果命中,则直接从本地获取缓存资源,不会发请求到服务器

  • 当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些 request header验证这个资源是否命中协商缓存,称为 http 再验证,如果命中,服务器将请求返回,但不返回资源,而是告诉客户端直接从缓存中获取,客户端收到返回后就会从缓存中获取资源

  • 强缓存和协商缓存共同之处在于,如果命中缓存,服务器都不会返回资源; 区别是,强缓存不对发送请求到服务器,但协商缓存会

  • 当协商缓存也没命中时,服务器就会将资源发送回客户端

  • 当 ctrl+f5 强制刷新网⻚时,直接从服务器加载,跳过强缓存和协商缓存

-当 f5 刷新网⻚时,跳过强缓存,但是会检查协商缓存

强缓存

  • Expires (该字段是 http1.0 时的规范,值为一个绝对时间的 GMT 格式的时间字符串,代表缓存资源的过期时间)

  • Cache-Control:max-age (该字段是 http1.1 的规范,强缓存利用其 max-age 值来判断缓存资源的最大生命周期,它的值单位为秒)

协商缓存

  • Last-Modified (值为资源最后更新时间,随服务器 response 返回)

  • If-Modified-Since (通过比较两个时间来判断资源在两次请求期间是否有过修改,如果没有修改,则命中协商缓存)

  • ETag (表示资源内容的唯一标识,随服务器 response 返回)

  • If-None-Match (服务器通过比较请求头部的 If-None-Match 与当前资源的 ETag 是否一致来判断资源是否在两次请求之间有过修改,如果没有修改,则命中协商缓存)