写在前面
第二篇来啦!冲!冲!冲!
第一篇在这里js数组所有内置方法简述以及手动实现(一)
因为有一次面试碰到了问有没有用过数组所有的内置方法?、是否清楚所有内置方法的参数和使用?当时并没有能全部答出来,所以决定从头理一篇所有的数组内置方法,并且自己实现一遍。主要是知识梳理,读者们也能从头梳理一遍。下面的方法尽量会全部自己实现,实在有困难的会google,然后注明出处。所有源码在GITHUB。
indexOf()
搜索数组中的元素,并返回它所在的位置。
例子?
let a = [1,2,3,NaN]
a.indexOf(2) // 1
实现
Array.prototype.indexOf2 = function (el, start = 0) {
if (start >= this.length || start < 0) return -1
for (let i = start; i < this.length; i++) {
if (el === this[i]) {
return i
}
}
return -1
}
isArray()
判断对象是否为数组。
例子?
let a = [1,2,3,NaN]
Array.isArray(a) // true
实现
Array.isArray2 = function (array) {
return Object.prototype.toString.call(arg) === '[object Array]'
}
join()
把数组的所有元素放入一个字符串。
例子?
let a = [1,2,3,NaN]
a.join(',') // '1,2,3,NaN'
实现
Array.prototype.join2 = function (separator = '') {
let res
for (let i = 0; i < this.length; i++) {
if (!res) {
res = this[i]
} else {
res += separator + this[i]
}
}
return res
}
keys()
返回数组的可迭代对象,包含原始数组的键(key)。
例子?
let a = [1,2,3,NaN]
let b = a.keys()
b.next() //{value: 0, done: false}
b.next() //{value: 1, done: false}
b.next() //{value: 2, done: false}
b.next() //{value: 3, done: false}
b.next() //{value: undefiend, done: true}
实现
function makeIterator(array) {
let nextIndex = 0;
return {
[Symbol.iterator]: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}
Array.prototype.keys2 = function () {
let res = []
for (let i = 0; i < this.length; i++) {
res.push(i)
}
return makeIterator(res).Symbol.iterator
}
迭代器详情请看阮一峰老师的ECMAScript 6 入门-Iterator 和 for...of 循环
lastIndexOf()
搜索数组中的元素,并返回它最后出现的位置。
例子?
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.lastIndexOf("Apple"); // 2
实现
Array.prototype.lastIndexOf2 = function (el, start = 0) {
start = Math.abs(start)
let res = -1
for (let i = start; i < this.length; i++) {
if (el === this[i] && res < i) {
res = i
}
}
if (start > 0) {
for (let i = 0; i < this.length - start; i++) {
if (el === this[i] && res < i) {
res = i
}
}
}
return res
}
map()
通过指定函数处理数组的每个元素,并返回处理后的数组。
例子?
var numbers = [4, 9, 16, 25];
numbers.map(Math.sqrt); // [2,3,4,5]
实现
Array.prototype.map2 = function (fn, context = null) {
const res = []
if (!context) {
context = this
}
for (let i = 0; i < context.length; i++) {
res.push(fn(context[i], i, context))
}
return res
}
pop()
删除数组的最后一个元素并返回删除的元素。
例子?
let a = [1,2,3]
a.pop() // 3,a:[1,2]
实现
Array.prototype.pop2 = function () {
const res = this[this.length - 1]
this.length -= 1
return res
}
push()
向数组的末尾添加一个或更多元素,并返回新的长度。
例子?
let a = []
a.push(1,2,3,4) // 4,a:[1,2,3,4]
实现
Array.prototype.push2 = function (...el) {
for (let i = 0; i < el.length; i++) {
this[this.length + i] = el[i]
}
return this.length
}
reduce()
将数组元素计算为一个值(从左到右)。
例子?
let a = [1,2,3,4]
function getSum(total, num) {
return total + num;
}
a.reduce(getSum) // 10
实现
Array.prototype.reduce2 = function (fn) {
let res = this[0]
for (let i = 1; i < this.length; i++) {
res = fn(res, this[i], i, this)
}
return res
}
reduceRight()
将数组元素计算为一个值(从右到左)。
例子?
let a = [1,2,3,4]
function getSum(total, num) {
return total + num;
}
a.reduceRight(getSum) // 10
实现
Array.prototype.reduceRight2 = function (fn) {
let res = this[this.length - 1]
for (let i = this.length - 2; i >= 0; i--) {
res = fn(res, this[i], i, this)
}
return res
}
reverse()
反转数组的元素顺序。
例子?
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.reverse();//["Mango", "Apple", "Orange", "Banana"]
实现
Array.prototype.reverse2 = function () {
let start = 0
let end = this.length - 1
while (start <= Math.floor(this.length / 2)) {
const temp = this[start]
this[start] = this[end]
this[end] = temp
start++
end--
}
return this
}
shift()
删除并返回数组的第一个元素。
例子?
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.shift() // "Banana"
实现
Array.prototype.shift2 = function () {
const res = this[0]
for (let i = 0; i < this.length; i++) {
if (this[i + 1]) {
this[i] = this[i + 1]
}
}
this.length -= 1
return res
}
slice()
选取数组的一部分,并返回一个新数组。
例子?
let a = [1,2,3,4,5]
a.slice(1,2) // [2]
实现
Array.prototype.slice2 = function (start, end) {
if (!end || end > this.length) {
end = this.length
}
if (!start) {
start = 0
}
let res = []
for (let i = start; i < end; i++) {
res.push(this[i])
}
return res
}
some()
检测数组元素中是否有元素符合指定条件。
例子?
let a = [1,2,3,8]
a.some(function (item) {
return item >= 8
}) // true
实现
Array.prototype.some2 = function (fn, context) {
if (!context) {
context = this
}
for (let i = 0; i < context.length; i++) {
const res = fn(context[i], i, context)
if (res === true) {
return res
}
}
return false
}
sort()
对数组的元素进行排序。
例子?
var points = [40,100,1,5,25,10];
points.sort(function(a,b){return b-a}); // [100,40,25,10,5,1]
实现
Array.prototype.sort2 = function (fn) {
const res = quickSort([...this], fn)
for (let i = 0; i < res.length; i++) {
this[i] = res[i]
}
return res
}
const quickSort = function(arr, fn) {
if (arr.length <= 1) { return arr; }
const pivotIndex = Math.floor(arr.length / 2);
const pivot = arr.splice(pivotIndex, 1)[0];
const left = [];
const right = [];
for (let i = 0; i < arr.length; i++){
if (fn(arr[i], pivot) < 0) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left, fn).concat([pivot], quickSort(right, fn));
};
splice()
从数组中添加或删除元素,返回删除的元素,会改变原数组。
例子?
let a = [1,2,6,4,5]
a.splice(2, 1, 3) // [6] a:[1,2,3,4,5,6]
实现
Array.prototype.splice2 = function (targetIndex, num, ...el) {
let k = num
const res = []
if (el.length <= 0) {
for (let i = targetIndex; i < this.length; i++) {
if (this[i + num]) {
res.push(this[i])
this[i] = this[i + num]
}
}
this.length -= num
} else {
let temp = []
for (let i = targetIndex; i < this.length; i++) {
if (res.length < num) {
res.push(this[i])
} else {
temp.push(this[i])
}
}
this.length = this.length - (temp.length + num)
let len = this.length + el.length
let j = 0
for (let i = targetIndex; i < len; i++) {
this[i] = el[j]
j++
}
j = 0
len = this.length + temp.length
for (let i = this.length; i < len; i++) {
this[i] = temp[j]
j++
}
}
return res
}
toString()
把数组转换为字符串,并返回结果(会递归转换)。
例子?
let a = [
[1, {a:1}],
[2,3]
]
a.toString() // "1,[object Object],2,3"
实现
Array.prototype.toString2 = function () {
return toStrng(this)
}
function toStrng (arr) {
if (Array.isArray(arr)) {
let res
for (let i = 0; i < arr.length; i++) {
if (!res) {
res = toStrng(arr[i])
} else {
res += ',' + toStrng(arr[i])
}
}
return res
} else if (typeof arr === 'number' || typeof arr === 'string') {
return arr
} else {
return Object.prototype.toString.call(arr)
}
}
unshift()
向数组的开头添加一个或更多元素,并返回新的长度。
例子?
let a = [3,4,5]
a.unshift(1,2) //5 a:[1,2,3,4,5]
实现
Array.prototype.unshift2 = function (...arr) {
const temp = []
for (let i = 0; i < this.length; i++) {
temp.push(this[i])
}
this.length = arr.length
for (let i = 0; i < this.length; i++) {
this[i] = arr[i]
}
const len = this.length + temp.length
let j = 0
for (let i = arr.length; i < len; i++) {
this[i] = temp[j]
j++
}
return len
}
最后
用了两大篇文章终于是把几乎所有方法都写完了,历时三个月哈哈,中间懒了两个月。写完之后收获不小,特别是在项目中用到的时候,不再需要再翻文档找到使用方法和注意事项了,直接就是用!
说实话从头理到尾并没有说增长了什么新知识,然后自己实现的方法也没有说多么完善多么好,但是写完之后不管是面试官问还是自己用都会变得信手拈来。到此结束了。
第一篇在这里js数组所有内置方法简述以及手动实现(一)。
所有源码在GITHUB,欢迎Star。
如果有什么不足或错误的地方,欢迎读者评论和留言
当然,要是本文对你有所帮助,欢迎点赞和转发,谢谢?
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!