push
Array.prototype._push = function (...args) {
let arr = this
let l = arr.length
let len = l + args.length
let index = 0
while (index < args.length) {
arr[l + index] = args[index]
index++
}
return len //push返回值是添加元素后数组的长度
}
pop
Array.prototype._pop = function () {
let arr = this
let l = arr.length
let result
if (l > 0) {
result = arr[l - 1]
arr.length--
}
return result
}
unshift
Array.prototype._unshift = function (...args) {
let arr = this
let l = arr.length
let len = l + args.length
let i = 1
while (i <= l) {
arr[len - i] = arr[l - i]
i++
}
let j = 0
while (j < args.length) {
arr[j] = args[j]
j++
}
return len //返回数组长度
}
shift
Array.prototype._shift = function () {
let arr = this
let result
if (arr.length > 0) {
result = arr[0]
let index = 0
while (index < arr.length - 1) {
arr[index] = arr[index + 1]
index++
}
arr.length--
}
return result
}
reverse
Array.prototype._reverse = function () {
let arr = this
if (arr.length > 1) {
let l = 0;
let r = arr.length - 1
while (l < r) {
[arr[l], arr[r]] = [arr[r], arr[l]]
l++
r--
}
}
return arr
}
splice
Array.prototype._splice = function (s, n = Infinity, ...args) {
let arr = this
let result = []
let left = []
let right = []
let temp
if (s >= 0 && s < arr.length) { //限制删除的开始位置在0 - arr.length 之间(未考虑负数的情况))
n = Math.min(n, arr.length - s) // 限制最多只能删除数组的个数
for (let i = 0; i < arr.length; i++) {
if (i < s) {
left.push(arr[i])
} else {
if (n > 0) {
result[result.length] = arr[s + result.length]
n--
} else {
right.push(arr[i])
}
}
}
if (args.length > 0) {
temp = [...left, ...args, ...right] // 拼接要添加的值
} else {
temp = [...left, ...right]
}
arr.length = temp.length // 修改原数组,将模版数组的值copy到原数组
for (let i = 0; i < temp.length; i++) {
arr[i] = temp[i]
}
}
return result //返回删除的值
}
fill
Array.prototype._fill = function (val, start = 0, end = Infinity) {
let arr = this
let len = arr.length
start = start < 0 ? Math.max(start + len, 0) : Math.min(start, len)
end = end < 0 ? Math.max(end + len, start) : Math.min(end, len)
while (start < end) {
arr[start++] = val
}
return arr
}
以上是含有副作用的数组方法,使用后会改变数组本身,带有副作用的方法有:push、pop,unshift,shift,splice,reverse,sort,fill(如果还有其他的欢迎指出)
map
Array.prototype._map = function(cb){
if(typeof cb !== 'function') {
throw new TypeError(cb + ' is not a function')
}
let T
let arr = this
let len = arr.length
let result = new Array(len)
if(arguments.length > 1){ //map的的第二个参数为调用回调函数cb的this指向
T = arguments[1]
}
let index = 0
while(index<len){
if(index in arr){ // 稀疏数组不做处理,例如[1,2,,,5],只处理下标为:0,1,4
result[index] = cb.call(T,arr[index],index,arr) //回调函数接收3个参数(当前索引对应的值,索引,数组本身)
}
index++
}
return result
}
reduce
Array.prototype._reduce = function (cb) {
if (typeof cb !== 'function') {
throw new TypeError(cb + ' is not a function')
}
let index, result
let arr = this
let len = arr.length
index = 0
if (arguments.length > 1) { //reduce第二个参数为初始值
result = arguments[1]
} else { // 如果没有传将取数组开头的第一个非稀疏值的元素
while (index < len && !(index in arr)) { //例如[,,30,40,50],初始值为30,遍历就会从40开始,所以下标index会从3开始
index++
}
if (index >= len) {
throw Error('this is a empty array')
}
result = arr[index++]
}
while (index < len) {
if (index in arr) {
result = cb(result, arr[index], index, arr) // cb接受4个参数,1累计值,2数组当前值,3当前索引,4原数组
}
index++
}
return result
}
filter
Array.prototype._filter = function (cb) {
if (typeof cb !== 'function') {
throw new TypeError((cb + ' is not a function'))
}
let T
let arr = this
let len = arr.length
let result = []
if (arguments.length > 1) {
T = arguments[1]
}
let index = 0
while (index < len) {
if (index in arr) {
if (cb.call(T, arr[index], index, arr)) {//当cb结果为true时添加值到result
result.push(arr[index])
}
}
index++
}
return result
}
find
Array.prototype._find = function (cb) {
if (typeof cb !== 'function') {
throw new TypeError((cb + ' is not a function'))
}
let arr = this
let len = arr.length
let T = arguments[1]
let result
let index = 0
while (index < len) {
if (cb.call(T, arr[index], index, arr)) {
return result = arr[index] //返回第一个满足条件的值
}
index++
}
return result
}
findIndex
Array.prototype._findIndex = function (cb) {
if (typeof cb !== 'function') {
throw new TypeError((cb + ' is not a function'))
}
let arr = this
let len = arr.length
let T = arguments[1]
let result = -1
let index = 0
while (index < len) {
if (cb.call(T, arr[index], index, arr)) {
return result = index //返回第一个满足条件的下标,一直未满足返回-1
}
index++
}
return result
}
some
Array.prototype._some = function (cb) {
if (typeof cb !== 'function') {
throw new TypeError((cb + ' is not a function'))
}
let arr = this
let len = arr.length
let T = arguments[1]
let index = 0
while (index < len) {
if (index in arr && cb.call(T, arr[index], index, arr)) { //检查数组中只要有一个满足条件的元素就返回true
return true
}
index++
}
return false
}
every
Array.prototype._every = function (cb) {
if (typeof cb !== 'function') {
throw new TypeError((cb + ' is not a function'))
}
let arr = this
let len = arr.length
let T = arguments[1]
let index = 0
while (index < len) {
if (index in arr) {
if (!cb.call(T, arr[index], index, arr)) return false // 只要有一项不满足条件就返回false
}
index++
}
return true // 全部满足返回true
}
forEach
Array.prototype._forEach = function (cb) { //forEach执行后无法跳出循环,除非抛出一个异常,如果需要提前跳出建议使用其他遍历方法
if (typeof cb !== 'function') {
throw new TypeError((cb + ' is not a function'))
}
let arr = this
let len = arr.length
let T = arguments[1]
let index = 0
while (index < len) {
if (index in arr) {
cb.call(T, arr[index], index, arr)
}
index++
}
}
flat
Array.prototype._flat = function () { // flat 是es10推出的,使用时要注意兼容性
let arr = this
function fn (arr) { //递归版
return arr.reduce((acc, cur) => acc.concat(Array.isArray(cur) ? fn(cur) : cur), [])
}
return fn(arr)
}
// function flatDeep (arr) { //循环版
// let temp = [...arr]
// let result = []
// while (temp.length) {
// let item = temp.pop()
// if (Array.isArray(item)) {
// temp.push(...item)
// } else {
// result.push(item)
// }
// }
// return result.reverse()
// }
以上的方法部分参考[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array)数组的polyfill