32个JS中高级问题(内容非原创,只是归纳迁移)

本文归纳了32个JavaScript中高级问题,涵盖数组扁平化、去重、类数组转化、Array方法、Function方法、防抖节流、柯里化、模拟new操作、深拷贝等,以及Promise、JSONP、AJAX等网络请求技术,还包括事件模块、图片懒加载等前端优化技巧。
摘要由CSDN通过智能技术生成

01.数组扁平化

数组扁平化是指将一个多维数组变为一个一维数组

const arr = [1, [2, [3, [4, 5]]], 6]
// => [1, 2, 3, 4, 5, 6]
方法一:使用flat(depth)

depth是一个可选的参数,指定要提取嵌套数组的结构深度,默认值为 1;
flat的返回值是一个包含将数组与子数组中所有元素的新数组。

const res1 = arr.flat(Infinity) //Infinity表示无穷大
方法二:利用正则表达式

但arr只能是Number, String, Boolean, Array, 扁平对象,即那些能够被 JSON 直接表示的数据结构。

const res2 = JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']')
方法三:使用reduce函数
const flatten = arr => {
   
  return arr.reduce((pre, cur) => {
   
    return pre.concat(Array.isArray(cur) ? flatten(cur) : cur)
  }, [])
}
const res3 = flatten(arr)
方法四:使用递归函数

const res4 = []
const fn = arr => {
   
  for (let i = 0; i < arr.length; i++) {
   
    if (Array.isArray(arr[i])) {
   
      fn(arr[i])
    } else {
   
      res5.push(arr[i])
    }
  }
}
fn(arr)

02.数组去重

const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {
   }, {
   }]
// => [1, '1', 17, true, false, 'true', 'a', {}, {}]
方法一:使用Set对象
const res1 = Array.from(new Set(arr))
方法二:两层for循环+splice

const unique1 = arr => {
   
  let len = arr.length
  for (let i = 0; i < len; i++) {
   
    for (let j = i + 1; j < len; j++) {
   
      if (arr[i] === arr[j]) {
   
        arr.splice(j, 1)
        // 每删除一个树,j--保证j的值经过自加后不变。同时,len--,减少循环次数提升性能
        len--
        j--
      }
    }
  }
  return arr
}
方法三:利用indexOf
const unique2 = arr => {
   
  const res = []
  for (let i = 0; i < arr.length; i++) {
   
    if (res.indexOf(arr[i]) === -1) res.push(arr[i])
  }
  return res
}
方法四:利用include
const unique3 = arr => {
   
  const res = []
  for (let i = 0; i < arr.length; i++) {
   
    if (!res.includes(arr[i])) res.push(arr[i])
  }
  return res
}
方法五:利用filter
const unique4 = arr => {
   
  return arr.filter((item, index) => {
   
    return arr.indexOf(item) === index
  })
}
方法五:利用filter
const unique5 = arr => {
   
  const map = new Map()
  const res = []
  for (let i = 0; i < arr.length; i++) {
   
    if (!map.has(arr[i])) {
   
      map.set(arr[i], true)
      res.push(arr[i])
    }
  }
  return res
}

03.类数组转化为数组

类数组是具有length属性,但不具有数组原型上的方法。常见的类数组有arguments、DOM操作方法返回的结果。

方法一:Array.from
Array.from(document.querySelectorAll('div'))
方法二:Array.prototype.slice.call()
Array.prototype.slice.call(document.querySelectorAll('div'))
方法三:扩展运算符
[...document.querySelectorAll('div')]
方法四:利用concat

Array.prototype.concat.apply([], document.querySelectorAll('div'))

04.Array.prototype.filter

Array.prototype.filter = function(callback, thisArg) {
   
  if (this == undefined) {
   
    throw new TypeError('this is null or not undefined')
  }
  if (typeof callback !== 'function') {
   
    throw new TypeError(callback + 'is not a function')
  }
  const res = []
  // 让O成为回调函数的对象传递(强制转换对象)
  const O = Object(this)
  // >>>0 保证len为number,且为正整数
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
   
    // 检查i是否在O的属性(会检查原型链)
    if (i in O) {
   
      // 回调函数调用传参
      if (callback.call(thisArg, O[i], i, O)) {
   
        res.push(O[i])
      }
    }
  }
  return res
}

x >>> 0本质上就是保证x有意义(为数字类型),且为正整数,在有效的数组范围内(0 ~ 0xFFFFFFFF),且在无意义的情况下缺省值为0。

05.Array.prototype.map

Array.prototype.map = function(callback, thisArg) {
   
  if (this == undefined) {
   
    throw new TypeError('this is null or not defined')
  }
  if (typeof callback !== 'function') {
   
    throw new TypeError(callback + ' is not a function')
  }
  const res = []
  // 同理
  const O = Object(this)
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
   
    if (i in O) {
   
      // 调用回调函数并传入新数组
      res[i] = callback.call(thisArg, O[i], i, this)
    }
  }
  return res
}

06.Array.prototype.forEach

Array.prototype.forEach = function(callback, thisArg) {
   
  if (this == null) {
   
    throw new TypeError('this is null or not defined')
  }
  if (typeof callback !== "function") {
   
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值