首页 > 其他分享 >js数组-实例方法:Array.prototype.at,Array.prototype.concat,Array.prototype.copyWithin

js数组-实例方法:Array.prototype.at,Array.prototype.concat,Array.prototype.copyWithin

时间:2024-12-16 20:43:41浏览次数:9  
标签:index copyWithin len length 数组 Array prototype

Array.prototype.at()

  1. at() 方法接收一个整数值并返回该索引对应的元素,允许正数和负数。负整数从数组中的最后一个元素开始倒数

  2. 语法

    • at(index)
  3. 参数

    • index
      • 要返回的数组元素的索引(从零开始),会被转换为整数。负数索引从数组末尾开始计数——如果 index < 0,则会访问 index + array.length 位置的元素
  4. 返回值

    • 返回数组中与给定索引匹配的元素。如果 index < -array.length 或 index >= array.length,则总是返回 undefined,而不会尝试访问相应的属性
  5. Array.prototype.myAt()

Array.prototype.myAt = function (index) {
  // 如果index大于数组的长度或者数组的长度加上index小于0,则超出数组的范围,返回undefined
  if (index < -this.length || index >= this.length) {
    return undefined
  } else if (index >= 0) {
    // index大于等于0,返回对应位置的数组元素
    return this[index]
  } else {
    // index小于0,返回数组长度加上index位置的元素
    return this[this.length + index]
  }
}

Array.prototype.concat()

  1. Array 实例的 concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
  2. 语法
    • concat()
    • concat(value0)
    • concat(value0, value1)
    • concat(value0, value1, /* … ,*/ valueN)
  3. 参数
    • value1、……、valueN 可选
    • 数组和/或值,将被合并到一个新的数组中。如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝。详情请参阅下文描述
  4. 返回值
    • 新的 Array 实例
  5. Array.prototype.myConcat()
Array.prototype.myConcat = function (...rest) {
  // 如果设置this为undefined或者null,报错
  if (this === undefined || this === null) {
    throw new TypeError('Array.prototype.myConcat called on null or undefined')
  }
  function parseParam(param, isThis = false) {
    let newArray = []
    // 判断param类型
    switch (Object.prototype.toString.call(param)) {
      // 如果是数组,字符串,symbol,BigInt,Boolean
      case '[object String]':
      case '[object Number]':
      case '[object Symbol]':
      case '[object BigInt]':
      case '[object Boolean]':
        // 数组类型不能设置[Symbol.isConcatSpreadable]属性,但是作为this的话需要转为Number的对象
        if (isThis) {
          newArray.push(Object(param))
        } else {
          newArray.push(param)
        }

        break
      // 如果是数组
      case '[object Array]':
        // 默认展开,如果设置了[Symbol.isConcatSpreadable]值为false时直接将param添加到新数组中 数组的[Symbol.isConcatSpreadable]默认不设置,为undefined,效果等于[Symbol.isConcatSpreadable]值为true
        if (param[Symbol.isConcatSpreadable] === false) {
          newArray.push(param)
        } else {
          // 因为存在稀疏数组的情况,需要判断值是否是empty:forEach方法会跳过empty不处理
          param.forEach((item, index) => {
            newArray[index] = item
          })
        }
        break
      default:
        // 如果是对象:类数组对象结构{0:0,1:1,length:2},需要将[Symbol.isConcatSpreadable]值设置为true才能展开加入到新数组中,否则直接整个加入到新数组
        // 其他类型数据,需要根据是否设置[Symbol.isConcatSpreadsble]值为true来判断是否需要展开加入到新数组中
        if (param[Symbol.isConcatSpreadable]) {
          // 判断是否是可迭代数组,已经设置过数组,默认为除数组和对象之外的其他可迭代模式:Set,Map,NodeList,HTMLCollection,arguments和具有length和迭代属性的object等
          // 不能和数组同时处理,因为类数组对象上没有forEach方法
          // 基础数据类型不能设置[Symbol.isConcatSpreadable]属性
          if (param[Symbol.iterator]) {
            newArray = [...param]
          } else {
            const len = param.length
            for (let i = 0; i < len; i++) {
              // 存在稀疏数组的情况
              if (param.hasOwnProperty(i)) {
                newArray[i] = param[i]
              }
            }
          }
        } else {
          newArray.push(param)
        }
        break
    }
    return newArray
  }
  // 首先需要处理this
  let newArr = parseParam(this, true)
  // 处理参数
  rest.forEach((item) => {
    // 设置前一个index值,newArr数组每次将下标为[newArr.length + index - prevIndex - 1]的值更新为item
    let prevIndex = -1
    parseParam(item).forEach((item, index) => {
      newArr[newArr.length + index - prevIndex - 1] = item
      prevIndex = index
    })
  })
  return newArr
}

Array.prototype.copyWithin()

  1. copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度
  2. 语法
    • copyWithin(target)
    • copyWithin(target, start)
    • copyWithin(target, start, end)
  3. 参数
    • target
      • 序列开始替换的目标位置,以 0 为起始的下标表示,且将被转换为整数
      • 负索引将从数组末尾开始计数——如果 target < 0,则实际是 target + array.length。
      • 如果 target < -array.length,则使用 0。
      • 如果 target >= array.length,则不会拷贝任何内容。
      • 如果 target 位于 start 之后,则复制只会持续到 array.length 结束(换句话说,copyWithin() 永远不会扩展数组)。
    • start
      • 要复制的元素序列的起始位置,以 0 为起始的下标表示,且将被转换为整数
      • 负索引将从数组末尾开始计数——如果 start < 0,则实际是 start + array.length。
      • 如果省略 start 或 start < -array.length,则默认为 0。
      • 如果 start >= array.length,则不会拷贝任何内容。
    • end(可选)
      • 要复制的元素序列的结束位置,以 0 为起始的下标表示,且将被转换为整数。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素
      • 负索引将从数组末尾开始计数——如果 end < 0,则实际是 end + array.length。
      • 如果 end < -array.length,则使用0
      • 如果省略 end 或 end >= array.length,则默认为 array.length,这将导致直到数组末尾的所有元素都被复制
      • 如果 end 位于 start 之前,则不会拷贝任何内容。
  4. 返回值
    • 改变后的数组
  5. Array.prototype.myCopyWithin()
Array.prototype.myCopyWithin = function (target, start, end) {
  // this如果为不可迭代对象的话返回对象本身,如果为基础数据类型的话,返回基础数据类型组构成的对象
  switch (Object.prototype.toString.call(this)) {
    case '[object String]':
    case '[object Number]':
    case '[object Boolean]':
    case '[object Symbol]':
    case '[object BigInt]':
    case '[object Undefined]':
    case '[object null]':
      return Object(this)
    case '[object Array]':
      if (target === undefined) {
        return this
      }
      const len = this.length
      let newTarget = getNum(target, len),
        newStart = start ? getNum(start, len) : 0,
        newEnd = end ? getNum(end, len) : len
      if (newTarget === len || newStart === len || newStart >= newEnd) {
        return this
      } else {
        // 存在稀疏数组的情况
        // 获取到被拷贝内容组成的数组
        const copy = this.slice(newStart, newEnd)
        // 存在2种情况
        // 1: copy的数组长度大于等于从target到len长度,此时只取copy中0到len - target的值,即copy.slice(0, len - target)
        // 2: copy的数组长度等于target到len的长度,此时取所有的copy后,将原数组最后没有被复制的部分需要拼接到数组的最后
        if (copy.length >= len - newTarget) {
          return [].concat(
            this.slice(0, newTarget),
            this.slice(newStart, newEnd)
          )
        } else {
          return [].concat(
            this.slice(0, newTarget),
            this.slice(newStart, newEnd),
            this.slice(newTarget + newEnd - newStart, len)
          )
        }
      }
    default:
      let thisArr = []
      // 如果具有迭代器,则将其转为数组
      if (target !== undefined && this.hasOwnProperty('length')) {
        // 如果是具有length的可迭代对象
        const len = this.length
        let newTarget = getNum(target, len),
          newStart = start ? getNum(start, len) : 0,
          newEnd = end ? getNum(end, len) : len
        const newObj = {...this}
        while (newStart < newEnd && newTarget < len) {
          if (this.hasOwnProperty(newStart)) {
            newObj[newTarget] = this[newStart]
          }
          newStart++
          newTarget++
        }
        return newObj
      } else {
        return this
      }
  }
}

标签:index,copyWithin,len,length,数组,Array,prototype
From: https://www.cnblogs.com/shenhf/p/18607202

相关文章

  • js中Iterable对象和Array有什么区别?
    在JavaScript中,Iterable对象和Array都是可以用来遍历的数据结构,但它们之间存在一些关键的区别。1.定义和本质Iterable:在JavaScript中,Iterable是一个接口,表示任何对象都可以被遍历。如果一个对象实现了Symbol.iterator方法,那么它就被认为是Iterable的。Iterable本身并不是一个......
  • Z-BlogPHP 应用启用时提示“array_key_exists() expects parameter 2 to be array, bo
    当您在使用Z-BlogPHP时遇到“array_key_exists()expectsparameter2tobearray,boolgiven”的错误,通常是因为数据库表中的数据不全或为空表造成的。以下是一些解决此问题的方法:检查数据库表:错误提示中明确指出 array_key_exists() 函数期望第二个参数为数组,但实际......
  • C#学习笔记(一) Array学习笔记
    之前一直学习各种基础知识,光学习,没有总结,趁着有时间,总结总结C#有关知识Array类是最基础的数组类,官方文档截图如下:Array是一个抽象类,不能实例化,只能使用里面的方法,属性。Array类不是System.Collections命名空间的一部分。但是,它仍被视为集合,因为它基于IList接口。Array......
  • 【java】 随笔 charAt,Random,ArrayList
    1.charAtcharch=str.charAt(i)  根据索引来获取字符串中的字符到ch中2.Random       Random类用来生成随机数字    (1)导包        importjava.util.Random;    (2)创建         Randomr=newRand......
  • ArrayList的常用成员方法
    1.ArrayList常用成员方法可以大致分为4种,增删改查1.增1.publicbooleanadd(Ee)将括号里的元素直接添加到集合中,添加的元素按照顺序依次排列。其中,E表示泛型<>里的类型,只能添加泛型限定的数据我们发现上图中即使没有使用变量接收返回值,也依旧能达成我们的目的。实际上,a......
  • [LeetCode] 1524. Number of Sub-arrays With Odd Sum
    Givenanarrayofintegersarr,returnthenumberofsubarrayswithanoddsum.Sincetheanswercanbeverylarge,returnitmodulo109+7.Example1:Input:arr=[1,3,5]Output:4Explanation:Allsubarraysare[[1],[1,3],[1,3,5],[3],[3,5],[5]]Allsu......
  • JS代码片段-Array数组克隆的几种方法
    JavaScript自身提供了几种克隆数组的方法,以下做了汇总,以作参考:1.展开运算符(...) ES6引入了展开运算符(...),这是创建数组浅克隆最常见的方法。leta=[1,2,3,4,5];letb=[...a];2.Array.from()leta=[1,2,3,4,5];letb=Array.from(a);3.Array.prototype.s......
  • javascript-Array
    1.序1.javascript数组索引是32位,自0开始。2.数组动态扩张和收缩。3.数组都有length属性,非离散数组Length表示数组中元素个数。离散数组,length大于最大元素的下标。4.数组属性继承于Array.prototype。大多数方法是泛型的。可以在数组和类数组对象中工作。7.1.1Arrayliterals......
  • ArrayBuffer和Blob有什么区别?
    ArrayBuffer和Blob都是JavaScript中用于表示二进制数据的对象,但在用途和底层实现上有所不同。理解它们的关键区别在于如何访问和使用数据。ArrayBuffer:底层:ArrayBuffer代表内存中的一块原始二进制数据,它本身不提供读取或写入数据的方法。它更像是一个底层的“数据容......
  • Array(3)和Array(3, 4)的区别是什么?
    在前端开发中,Array(3)和Array(3,4)创建JavaScript数组的方式不同,导致生成的数组也不同。Array(3):创建一个长度为3的空数组。重要的是,这些元素实际上并没有被赋值,它们处于一种“空槽”状态。当你尝试访问这些元素时,你会看到undefined或空值。可以把它想象成预......