Array.prototype.at()
-
at() 方法接收一个整数值并返回该索引对应的元素,允许正数和负数。负整数从数组中的最后一个元素开始倒数
-
语法
- at(index)
-
参数
- index
- 要返回的数组元素的索引(从零开始),会被转换为整数。负数索引从数组末尾开始计数——如果 index < 0,则会访问 index + array.length 位置的元素
- index
-
返回值
- 返回数组中与给定索引匹配的元素。如果 index < -array.length 或 index >= array.length,则总是返回 undefined,而不会尝试访问相应的属性
-
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()
- Array 实例的 concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
- 语法
- concat()
- concat(value0)
- concat(value0, value1)
- concat(value0, value1, /* … ,*/ valueN)
- 参数
- value1、……、valueN 可选
- 数组和/或值,将被合并到一个新的数组中。如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝。详情请参阅下文描述
- 返回值
- 新的 Array 实例
- 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()
- copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度
- 语法
- copyWithin(target)
- copyWithin(target, start)
- copyWithin(target, start, end)
- 参数
- 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 之前,则不会拷贝任何内容。
- target
- 返回值
- 改变后的数组
- 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