实现 Array 的原生方法
大约 6 分钟
forEach 方法
- 参数有
callback
和thisArg
- 遍历所有元素并逐个执行
callback
type fnType<T> = (value: T, index: number, array: T[]) => void
interface Array<T> {
myForEach(callback: fnType<T>, thisArg?: any): void
}
Object.defineProperty(Array.prototype, 'myForEach', {
enumerable: false,
writable: false,
configurable: false,
value: function myForEach<T>(this: T[], callback: fnType<T>, thisArg?: any) {
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, thisArg)
}
}
})
Array.prototype.myForEach = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
thisArg = thisArg || this
fot (let i = 0; i < this.length; i ++) {
callback.call(thisArg, this[i], i, this)
}
}
map 方法
- 参数有
callback
和thisArg
- 返回一个数组,由原数组每个元素调用
callback
的返回值组成
type fnType<T> = (value: T, index: number, array: T[]) => unknown
interface Array<T> {
myMap(callback: fnType<T>, thisArg?: any): unknown[]
}
Object.defineProperty(Array.prototype, 'myMap', {
enumerable: false,
writable: false,
configurable: false,
value: function myMap<T>(this: T[], callback: fnType<T>, thisArg?: any): unknown[] {
const result = new Array<unknown>()
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
result.push(callback.call(thisArg, this[i], i, this))
}
return result
}
})
Array.prototype.myMap = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
const result = new Array()
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
result.push(callback.call(thisArg, this[i], i, this))
}
return result
}
filter 方法
- 参数有
callback
和thisArg
- 返回一个数组,其各个元素均符合
callback
的测试条件
type fnType<T> = (value: T, index: number, array: T[]) => unknown
interface Array<T> {
myFilter(callback: fnType<T>, thisArg?: any): T[]
}
Object.defineProperty(Array.prototype, 'myFilter', {
enumerable: false,
writable: false,
configurable: false,
value: function myFilter<T>(this: T[], callback: fnType<T>, thisArg?: any): T[] {
const result = new Array<T>()
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this) && result.push(this[i])
}
return result
}
})
Array.prototype.myFilter = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
const result = new Array()
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this) && result.push(this[i])
}
return result
}
every 方法
- 参数有
callback
和thisArg
- 若所有元素都符合
callback
的条件,返回true
,否则返回false
type fnType<T> = (value: T, index: number, array: T[]) => unknown
interface Array<T> {
myEvery(callback: fnType<T>, thisArg?: any): boolean
}
Object.defineProperty(Array.prototype, 'myEvery', {
enumerable: false,
writable: false,
configurable: false,
value: function myEvery<T>(this: T[], callback: fnType<T>, thisArg?: any): boolean {
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (!callback.call(thisArg, this[i], i, this)) return false
}
return true
}
})
Array.prototype.myEvery = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (!callback.call(thisArg, this[i], i, this)) return false
}
return true
}
some 方法
- 参数有
callback
和thisArg
- 若至少有一个元素符合
callback
的条件,返回true
,否则返回false
type fnType<T> = (value: T, index: number, array: T[]) => unknown
interface Array<T> {
mySome(callback: fnType<T>, thisArg?: any): boolean
}
Object.defineProperty(Array.prototype, 'mySome', {
enumerable: false,
writable: false,
configurable: false,
value: function mySome<T>(this: T[], callback: fnType<T>, thisArg?: any): boolean {
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) return true
}
return false
}
})
Array.prototype.myEvery = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) return true
}
return false
}
reduce 方法
- 参数有
callback
和initial
- 以上一次元素的计算结果作为
callback
的参数,直到最后一个元素并返回最终结果 - 若
initial
不为 undefined,以initial
作为初始值从索引为 0 的元素开始计算,否则以索引为 0 的元素作为初始值从索引为 1 的元素,开始计算 - 返回最终计算结果
type fnType<T> = (previous: T, current: T, currentIndex: number, array: T[]) => T
interface Array<T> {
myReduce(callback: fnType<T>, initial?: T): T
}
Object.defineProperty(Array.prototype, 'myReduce', {
enumerable: false,
writable: false,
configurable: false,
value: function myReduce<T>(this: T[], callback: fnType<T>, initial?: T): T {
let [start, result] = typeof initial === 'undefined' ? [1, this[0]] : [0, initial]
for (let i = start; i < this.length; i++) {
result = callback(result, this[i], i, this)
}
return result
}
})
Array.prototype.myReduce = function(callback, inital) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
let [start, result] = typeof initial === 'undefined' ? [1, this[0]] : [0, initial]
for (let i = start; i < this.length; i++) {
result = callback(result, this[i], i, this)
}
return result
}
reduceRight 方法
- 参数有
callback
和initial
- 以上一次元素的计算结果作为
callback
的参数,直到最后一个元素并返回最终结果 - 与 reduce 方法类似,但从数组尾开始计算
- 返回最终计算结果
type fnType<T> = (previous: T, current: T, currentIndex: number, array: T[]) => T
interface Array<T> {
myReduceRight(callback: fnType<T>, initial?: T): T
}
Object.defineProperty(Array.prototype, 'myReduceRight', {
enumerable: false,
writable: false,
configurable: false,
value: function myReduceRight<T>(this: T[], callback: fnType<T>, initial?: T): T {
let [start, result] = typeof initial === 'undefined' ? [this.length - 2, this[0]] : [this.length - 1, initial]
for (let i = start; i >= 0; i--) {
result = callback(result, this[i], i, this)
}
return result
}
})
Array.prototype.myReduceRight = function(callback, initial) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
let [start, result] = typeof initial === 'undefined' ? [this.length - 2, this[0]] : [this.length - 1, initial]
for (let i = start; i >= 0; i--) {
result = callback(result, this[i], i, this)
}
return result
}
find 方法
- 参数有
callback
和thisArg
- 返回第一个符合
callback
条件的元素
type fnType<T> = (element: T, index: number, array: T[]) => unknown
interface Array<T> {
myFind(callback: fnType<T>, thisArg?: any): T | undefined
}
Object.defineProperty(Array.prototype, 'myFind', {
enumerable: false,
writable: false,
configurable: false,
value: function myFind<T>(this: T[], callback: fnType<T>, thisArg?: any): T | undefined {
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) return this[i]
}
return undefined
}
})
Array.prototype.myFind = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) return this[i]
}
return undefined
}
findIndex 方法
- 参数有
callback
和thisArg
- 返回第一个符合
callback
条件的元素的索引
type fnType<T> = (element: T, index: number, array: T[]) => unknown
interface Array<T> {
myFindIndex(callback: fnType<T>, thisArg?: any): number
}
Object.defineProperty(Array.prototype, 'myFindIndex', {
enumerable: false,
writable: false,
configurable: false,
value: function myFindIndex<T>(this: T[], callback: fnType<T>, thisArg?: any): number {
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) return i
}
return -1
}
})
Array.prototype.myFindIndex = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('Callback must be a function')
}
thisArg = thisArg || this
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) return i
}
return -1
}
fill 方法
- 参数有
callback
、start
和end
- 用
value
填充数组从start
到end
前的所有元素 - 返回修改后的数组
interface Array<T> {
myFill(value: T, start?: number, end?: number): T[]
}
Object.defineProperty(Array.prototype, 'myFill', {
enumerable: false,
writable: false,
configurable: false,
value: function myFill<T>(this: T[], value: T, start: number = 0, end?: number): T[] {
end = end || this.length
for (let i = start; i < end; i++) {
this[i] = value
}
return this
}
})
Array.prototype.myFill = function(value, start = 0, end) {
end = end || this.length
for (let i = start; i < end; i++) {
this[i] = value
}
return this
}
includes 方法
- 参数有
value
和start
- 若数组包含
value
,返回true
,否则返回false
interface Array<T> {
myIncludes(value: T, start?: number): boolean
}
Object.defineProperty(Array.prototype, 'myIncludes', {
enumerable: false,
writable: false,
configurable: false,
value: function myIncludes<T>(this: T[], value: T, start: number = 0): boolean{
for (let i = start; i < this.length; i++) {
if (this[i] === value) return true
}
return false
}
})
Array.prototype.myIncludes = function(value, start = 0) {
for (let i = start; i < this.length; i++) {
if (this[i] === value) return true
}
return false
}
join 方法
- 参数有
separator
- 返回一个以
separator
作为分隔符连接各个元素的字符串
interface Array<T> {
myJoin(separator?: string): string
}
Object.defineProperty(Array.prototype, 'myJoin', {
enumerable: false,
writable: false,
configurable: false,
value: function myJoin<T>(this: T[], separator: string = ','): string {
let result = `${this[0]}`
for (let i = 1; i < this.length; i++) {
result += `${separator}${this[i]}`
}
return result
}
})
Array.prototype.myJoin = function(separator = ',') {
let result = `${this[0]}`
for (let i = 1; i < this.length; i++) {
result += `${separator}${this[i]}`
}
return result
}