最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • js数组所有内置方法简述以及手动实现(一)

    正文概述 掘金(nathan_ll)   2020-12-09   568

    写在前面

    因为有一次面试碰到了问有没有用过数组所有的内置方法?是否清楚所有内置方法的参数和使用?当时并没有能全部答出来,所以决定从头理一篇所有的数组内置方法,并且自己实现一遍。主要是知识梳理,读者们也能从头梳理一遍。下面的方法尽量会全部自己实现,实在有困难的会google,然后注明出处。

    concat

    用于连接数组,但是不会改变数组,会返回一个连接后的结果数组

    参数:可以是数组也可以是非数组

    例子?

    let a = [1, 2, 3]
    let b = [4,5]
    let c = [6,7,8,9]
    a.concat(b, c) // [1,2,3,4,5,6,7,8,9]
    

    简单实现

    Array.prototype.concat2 = function (...arrays) {
      let copy = this.slice(0) // 不用深度拷贝,因为原concat也没有深度拷贝
      for (let i = 0; i < arrays.length; i++) {
        const item = arrays[i]
        if (!Array.isArray(item)) { // 不是数组直接push进copy
          copy.push(item)
        } else { // 数组的话递归concat进行连接
          for (let j = 0; j < item.length; j++) {
            copy = copy.concat2(item[j])
          }
        }
      }
      return copy
    }
    

    时间复杂度: 大概是O(n)

    copyWithin

    用于拷贝数组的元素到原数组的另一个指定位置,会改变原数组。IE 11 及更早版本不支持 copyWithin() 方法

    参数描述
    target:Number拷贝的目标位置(必须)start:Number需要拷贝元素的开始位置(非必须,默认是0)end:Number需要拷贝元素的结束位置(非必须,默认是length)

    例子?

    let a = [1,2,3,4,5,6]
    a.copyWithin(2, 0, 1) // [1,2,1,4,5,6]
    

    简单实现

    Array.prototype.copyWithin2 = function (target, start, end) {
      start = start || 0
      end = end || this.length
      const copy = []
      for (let i = start; i < end; i++) {
        copy.push(this[i])
      }
      const len = this.length > copy.length ? copy.length : this.length // 判断需要遍历赋值的最长长度
      for (let i = 0, j = target; i < len; i++, j++) {
        if (j >= this.length) {
          break
        }
        this[j] = copy[i]
      }
      return this
    }
    

    entries

    返回数组的可迭代对象,不会修改源数组

    可迭代对象:这里推荐看阮一峰老师的Iterator 和 for...of 循环

    例子?

    let a = ['123', '456', '789']
    let b = a.entries()
    b.next() // {value: [0, '123'], done: false}
    for (let v of b) {
      console.log(v)
    }
    // [1, '456']
    // [2, '789']
    

    简单实现

    Array.prototype.entries2 = function () {
      return this[Symbol.iterator]()
    }
    Array.prototype[Symbol.iterator] = function () {
      var nextIndex = 0;
      return {
        next: function() {
          return nextIndex < this.length ?
            {value: this[nextIndex++], done: false} :
            {value: undefined, done: true};
        }
      }
    }
    

    every

    会遍历每个元素是否满足用户给出的回调函数,是返回true,否返回false,并且不会继续检查。

    不会对空数组检查,不会改变原数组

    例子?

    var ages = [32, 33, 16, 40];
    
    function checkAdult(age) {
        return age >= 18;
    }
    
    ages.every(checkAdult);// false
    

    实现

    Array.prototype.every2 = function (fn) {
      if (this.length > 0) {
        for (let i = 0; i < this.length; i++) {
          if (!fn(this[i])) {
            return false
          }
        }
      }
      return true
    }
    

    fill

    用一个特定的值替换指定位置的数组元素,改变原数组。

    参数:

    参数描述
    value必需。填充的值。start可选。开始填充位置。end可选。停止填充位置 (默认为 array.length)

    例子?

    var fruits = ["Banana", "Orange", "Apple", "Mango"];
    fruits.fill("Runoob", 2, 4); // Banana,Orange,Runoob,Runoob
    

    实现

    Array.prototype.fill2 = function (v, start = 0, end) {
      end = end || this.length
      for (let i = start; i < end; i++) {
        this[i] = v
      }
      return this
    }
    

    filter

    返回满足回调函数的元素数组,不会改变原数组

    例子?

    var ages = [32, 33, 16, 40];
    
    function checkAdult(age) {
        return age >= 18;
    }
    ages.filter(checkAdult);// [32, 33, 40]
    

    实现

    Array.prototype.filter2 = function (fn, ctx) {
      ctx = ctx || this
      const res = []
      for (let i = 0; i < this.length; i++) {
        if (fn.apply(ctx, [this[i], i, this])) {
          res.push(this[i])
        }
      }
      return res
    }
    

    find

    返回满足回调函数的第一个值

    不改变原数组,都不满足返回undefined

    例子?

    var ages = [3, 10, 18, 20];
     
    function checkAdult(age) {
        return age >= 18;
    }
     
    ages.find(checkAdult); // 18
    

    实现

    Array.prototype.find2 = function (fn, ctx) {
      ctx = ctx || this
      for (let i = 0; i < this.length; i++) {
        if (fn.apply(ctx, [this[i], i, this])) {
          return this[i]
        }
      }
      return
    }
    

    findIndex

    返回满足回调函数的第一个值的位置下标

    不满足返回-1

    不会改变原数组

    例子?

    var ages = [3, 10, 18, 20];
     
    function checkAdult(age) {
        return age >= 18;
    }
     
    ages.find(checkAdult); // 2
    

    实现

    Array.prototype.findIndex = function (fn, ctx) {
      ctx = ctx || this
      for (let i = 0; i < this.length; i++) {
        if (fn.apply(ctx, [this[i], i, this])) {
          return i
        }
      }
      return -1
    }
    

    forEach()

    数组每个元素都执行一次回调函数。不会修改原数组。但是当元素为引用类型时,会修改。

    例子?

    const b = [{v: 65}]
    b.forEach(v => v.v += 1)
    //b [{v: 66}]
    

    实现

    Array.prototype.forEach2 = function (fn, ctx = window) {
      for (let i = 0; i < this.length; i++) {
        fn.apply(ctx, [this[i], i, this])
      }
    }
    

    from()

    通过拥有 length 属性的对象或可迭代的对象来返回一个数组。(他有第二个参数,是个function,和map是一样的)

    例子?

    let a = {0: 'demo', 1: 'demo2', length: 2}
    let b = Array.from(a)
    console.log(b) //=>['demo', 'demo2']
    

    实现

    Array.from2 = function (data, mapFun = function (item) {return item}) {
      let res = []
      if (data.length) {
        for (let i = 0; i < data.length; i++) {
          res[i] = mapFun(data[i]) || null
        }
      } else if (typeof data[Symbol.iterator] === 'function') {
        data.forEach((item) => {
          res.push(mapFun(item))
        })
      }
      return res
    }
    

    includes()

    判断一个数组是否包含一个指定的值,包括NaN也能判断出来为true。

    例子?

    const a = [1,2,3,NaN]
    a.includes(NaN) // true
    

    实现

    Array.prototype.includes2 = function (el, fromIndex = 0) {
      if (typeof el === 'object') {
        return false
      }
      if (fromIndex < 0) {
        fromIndex = this.length + fromIndex
      }
      for (let i = fromIndex; i < this.length; i++) {
        if (el.toString() === 'NaN') {
          if (this[i].toString() === el.toString()) {
            return true
          }
        } else {
          if (this[i] === el) {
            return true
          }
        }
      }
      return false
    }
    

    总结

    这是第一篇,因为内置方法太多,剩下的放在第二篇,还在写哦...

    作者只是自己瞎写写,肯定会有很多地方实现的不好,欢迎来指正哦

    如果有什么不足或错误的地方,欢迎读者评论和留言

    当然,要是本文对你有所帮助,欢迎点赞和转发,谢谢?


    起源地下载网 » js数组所有内置方法简述以及手动实现(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元