Open logan70 opened 4 years ago
所有数组方法的实现均忽略参数校验、边界条件判断,主要关注核心逻辑的实现。
部分数组方法会基于Array.prototype.reduce方法来实现,关于reduce方法的讲解及实现详见彻底搞懂数组reduce方法
Array.prototype.reduce
reduce
MDN - Array.prototype.push()
push()方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
push()
push()方法可用于类数组对象,需要注意的是length不存在或无法转为数值时,将被设置为0,并从索引0开始添加元素。
Array.prototype._push = function(...args) { const len = Number(this.length) || 0 this.length = len for (arg of args) { this[this.length++] = arg } return this.length }
MDN - Array.prototype.reduceRight()
reduceRight()方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。
reduceRight()
之前已实现过reduce()方法,详情见文章开头,我们使用其来实现reduceRight()方法。
reduce()
Array.prototype._reduceRight = function(callback) { const len = this.length if (arguments.length >= 2) { return [...this].reverse().reduce((acc, cur, i) => { return callback(acc, cur, len - 1 - i, this) }, arguments[1]) } else { return [...this].reverse().reduce((acc, cur, i) => { return callback(acc, cur, len - 1 - i, this) }) } }
MDN - Array.prototype.reverse()
reverse()方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
reverse()
通过交换数组左右对应位置的值实现,这样只用迭代Math.floor(this.length / 2)次。
Math.floor(this.length / 2)
Array.prototype._reverse = function() { const len = this.length for (let i = 0; i < Math.floor(len / 2); i++) { const correspondIndex = len - 1 - i; [this[i], this[correspondIndex]] = [this[correspondIndex], this[i]] } return this }
MDN - Array.prototype.shift()
shift()方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
shift()
Array.prototype._shift = function() { if (!this.length) return undefined // 记录第一项并删除 const valToDel = this[0] delete this[0] // 之后项依次左移 for (let i = 0; i < this.length - 1; i++) { this[i] = this[i + 1] } // 删除最后一项 delete this[this.length - 1] // 修正数组长度 this.length-- return valToDel }
MDN - Array.prototype.slice()
slice()方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
slice()
Array.prototype._slice = function(beginIndex = 0, endIndex = this.length) { const begin = beginIndex < 0 ? Math.max(this.length + beginIndex, 0) : Math.min(beginIndex, this.length) const end = endIndex < 0 ? Math.max(this.length + endIndex, 0) : Math.min(endIndex, this.length) const count = end - begin if (count <= 0) return [] const result = new Array(count) for (let i = 0; i < count; i++) { if (i in this) { result[i] = this[begin + i] } } return result }
MDN - Array.prototype.some()
some()方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。
some()
some()方法具有短路特性,且会跳过数组稀疏项。
Array.prototype._some = function(callback, thisArg) { for (let i = 0; i < this.length; i++) { if (i in this && callback.call(thisArg, this[i], i, this)) { return true } } return false }
MDN - Array.prototype.splice()
splice()方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
splice()
Array.prototype._splice = function(startIndex, deleteCount = this.length - startIndex, ...items) { const len = this.length const start = startIndex < 0 ? Math.max(len + startIndex, 0) : Math.min(len, startIndex) const realDeleteCount = deleteCount <= 0 ? 0 : Math.min(len - start, deleteCount) const deleteVals = this.slice(start, start + realDeleteCount) const right = [...items, ...this.slice(start + realDeleteCount)] for (let i = 0; i < right.length; i++) { this[start + i] = right[i] } // 修正length属性,自动删除多余项 this.length = start + right.length return deleteVals }
MDN - Array.prototype.unshift()
unshift()方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。
unshift()
Array.prototype._unshift = function(...items) { const addCount = items.length if (addCount === 0) return this.length this.length += items.length for (let i = this.length - 1; i >= 0; i--) { if (i >= addCount) { this[i] = this[i - addCount] } else { this[i] = items[i] } } return this.length }
MDN - Array.prototype.values()
values()方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值,实现方法与keys()、entries()相似。
values()
keys()
entries()
Array.prototype._values = function(...items) { function *gen() { for (let i = 0; i < this.length; i++) { yield this[i] } } return gen.call(this) }
实现数组方法(下)
所有数组方法的实现均忽略参数校验、边界条件判断,主要关注核心逻辑的实现。
部分数组方法会基于
Array.prototype.reduce
方法来实现,关于reduce
方法的讲解及实现详见彻底搞懂数组reduce方法Array.prototype.push()
MDN - Array.prototype.push()
push()
方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。push()
方法可用于类数组对象,需要注意的是length不存在或无法转为数值时,将被设置为0,并从索引0开始添加元素。Array.prototype.reduceRight()
MDN - Array.prototype.reduceRight()
reduceRight()
方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。之前已实现过
reduce()
方法,详情见文章开头,我们使用其来实现reduceRight()
方法。Array.prototype.reverse()
MDN - Array.prototype.reverse()
reverse()
方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。通过交换数组左右对应位置的值实现,这样只用迭代
Math.floor(this.length / 2)
次。Array.prototype.shift()
MDN - Array.prototype.shift()
shift()
方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。Array.prototype.slice()
MDN - Array.prototype.slice()
slice()
方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。Array.prototype.some()
MDN - Array.prototype.some()
some()
方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。some()
方法具有短路特性,且会跳过数组稀疏项。Array.prototype.splice()
MDN - Array.prototype.splice()
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。Array.prototype.unshift()
MDN - Array.prototype.unshift()
unshift()
方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。Array.prototype.values()
MDN - Array.prototype.values()
values()
方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值,实现方法与keys()
、entries()
相似。