文章首发:CSDN

手写数组衍生方法

1.检测是否为数组

    <script>
var arr = [1,2,3]
//判断arr是否为数组,返回布尔值true 或false //法一:Array.isArray()
console.log(Array.isArray(arr));
//法二:instanceof
console.log( arr instanceof Array);
//法三:判断arr的构造函数constructor有无包含Array
console.log(arr.constructor.toString().indexOf('Array')>-1);
//arr.constructor为ƒ Array() { [native code] } //法四:用isPrototypeOf判断arr是否存在于Array的原型链中
console.log(Array.prototype.isPrototypeOf(arr));
/*
法五:万能判断变量类型方法Object.prototype.toString.call()
会返回一个形如 "[object XXX]" 的字符串
*/
console.log(Object.prototype.toString.call(arr).indexOf('Array')>-1);
//即console.log(Object.prototype.toString([])===Object.prototype.toString(arr));
</script>

2.类数组转化为数组

类数组对象,就是含有 length 属性且不是数组的对象,但结构表现上很像一个数组。

类数组对象主要有:

  • 普通函数中的argument
  • 一些获取 Dom 集合的方法,如document.querySelectorAll()、 document.getElementsByClassName、document.getElementsByTagName()等也会返回类数组对象
 <body>
<div>1</div>
<div>2</div>
<script>
let arg = document.querySelectorAll('div');
console.log(arg); //NodeList(2) //法一: 用Array.from
console.log(Array.from(arg)); //Array(2)
//法二 :扩展运算符
console.log([...arg]); //法三:用Array.prototype.slice.call():可将具有length属性的对象转成数组,因为slice方法返回一个新数组
console.log( Array.prototype.slice.call(arg));
//slice方法如果不传参数的话会返回原数组的一个拷贝,通过call显式绑定来实现使arguments也能调用slice方法。 //法四:利用concat
console.log(Array.prototype.concat.apply([], arg));
</script>
</body>

3.数组扁平化

数组扁平化是指将一个多维数组变为一个一维数组

   const arr = [1, [2, [3, [4, 5]]], 6]
// => [1, 2, 3, 4, 5, 6]
//法一:使用内置的flat()
const res1 = arr.flat(Infinity)
//法二:用正则表达式
const res2 = JSON.stringify(arr).replace(/\[|\]/g,"").split(',')
//此时数组元素为字符串类型,若用arr.join()会将中括号自动去掉 //法三:用 reduce 实现数组的 flat 方法(重点关注)
function flatmy(ary) {
//注意函数要有返回值
return ary.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatmy(cur) : cur)
}, [])
}
console.log(flatmy(arr)) // 法四:函数递归
const res4 = []
const fn = (arr) => {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
fn(arr[i])
} else {
res4.push(arr[i])
//或 res4 = res4.concat(arr[i])
}
}
return res4
} console.log(fn(arr))
//法五:调用toString
console.log(arr.toString()); //1,2,3,4,5,6
console.log(arr.toString().split(',').map(item => item-0)) //若没有map函数隐式转换则数组里的元素为字符串类型

4.数组去重

  const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}]
// => [1, '1', 17, true, false, 'true', 'a', {}, {}]
// 法一:用new Set方法
let res = Array.from(new Set(arr))
// 法二:用indexOf
let res2 = []
for(let v of arr){
if(res2.indexOf(v)==-1) res2.push(v)
} /*法三:用filter */
function myUnique(arr){
return arr.filter((v,index)=>{
return arr.indexOf(v)===index
})
}
// 法四:用sort,排序后相同的元素在相邻位置
function unique(arr) {
arr = arr.sort()
var res= []
for (var i = 0; i < arr.length; i++) {
if (arr[i] !== arr[i - 1]) {
res.push(arr[i])
}
}
return res
}
console.log(unique(arr))

5.数组使用Math.max

Math.max支持传入多个参数,但不可传入一个数组(否则为NaN),若想使用可用一下方法

Math.max.apply(null,arr)
Math.max(...arr)

手写数组内置方法

1. Array.prototype.filter

filter() 方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素

语法:var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

参数:

callback:用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。它接受以下三个参数

element:数组中当前正在处理的元素。

index可选:正在处理的元素在数组中的索引。

array可选:调用了 filter 的数组本身。

thisArg可选:执行 callback 时,用于 this 的值。

Array.prototype.myFilter = function(callback,thisArg){
if(typeof callback != 'function' ) {
throw new TypeError(callback +'不是函数')
}
if(!Array.isArray(this)){
throw new TypeError('必须为数组才可调用此方法')
}
let res = []
//确定回调函数的this指向,看是否传了第二个参数,若无则设为window调用
let context = arguments[1]||window
for(let i = 0; i < this.length; i++){
callback.call(context,this[i],i,this) && res.push(this[i])
}
return res
}

2. Array.prototype.map

map() 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成

语法:var new_array = arr.map(function callback(currentValue[, index[, array]]) [, thisArg]),参数大致与filter相同

  Array.prototype.myMap = function (callback, thisArg) {
if (typeof callback != 'function') {
throw new TypeError(callback + '不是函数');
}
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let res = []
let context = arguments[1] || window
for (let i = 0; i < this.length; i++) {
res.push(callback.call(context, this[i], i, this))
}
return res
};

3. Array.prototype.reduce(难点)

reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值

语法:Array.reduce(callback(previousValue, currentValue[, currentIndex[, array]])[, initialValue])

参数:

previousValue:上一次调用 callbackFn 时的返回值。第一次调用时为初始值initialValue||array[0]

currentValue:数组中正在处理的元素。在第一次调用时若指定了初始值 initialValue,其值则为 array[0],否则为 array[1]。

currentIndex:数组中正在处理的元素的索引

initialValue :可选,作为第一次调用 callback 函数时参数 previousValue 的值。若指定了 initialValue则 currentValue 将使用数组第一个元素

Array.prototype.myReduce = function (callback, initialValue) {
if (typeof callback != 'function') {
throw new TypeError(callback + '不是函数');
}
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let accumulator = initialValue
if(accumulator === undefined){
//若未设初始值则赋值为数组的第一个元素
accumulator = this[0]
//数组为空且初始值 initialValue 未提供时会报错
if(accumulator === undefined) throw new TypeError('无初始值时数组要为非空');
}
//若给定初始值则起始索引号为0
let startIndex = initialValue !== undefined ? 0 : 1;
for (let i = startIndex; i < this.length; i++) {
accumulator = callback.call(undefined,accumulator,this[i], i, this);
}
return accumulator;
};

4. Array.prototype.forEach

forEach() 方法对数组的每个元素执行一次给定的函数,注意返回值为undefined

语法:arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

 Array.prototype.myForEach = function (callback, thisArg) {
if (typeof callback != 'function') {
throw new TypeError(callback + '不是函数');
}
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let context = arguments[1] || window;
for (let i = 0; i < this.length; i++) {
callback.call(context, this[i], i, this);
}
};

5. Array.prototype.some

some() 方法测试数组中是不是至少有 1 个元素通过了被提供的函数测试。它返回的是一个 Boolean 类型的值。

语法:arr.some(callback(element[, index[, array]])[, thisArg])

 Array.prototype.mySome = function(callback,thisArg){
if (typeof callback != 'function') {
throw new TypeError(callback + '不是函数');
}
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let context = arguments[1] || window
for(let i =0 ; i < this.length; i++){
if( callback.call(context,this[i],i,this)){
return true
}
}
return false
}

6. Array.prototype.find

find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined

语法:Array.find(callback(element[, index[, array]])[, thisArg])

   Array.prototype.myFind = function(callback,thisArg){
if (typeof callback != 'function') {
throw new TypeError(callback + '不是函数');
}
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let context = arguments[1] || window
for(let i =0 ; i < this.length; i++){
if( callback.call(context,this[i],i,this)){
return this[i]
}
}
return undefined
}

7. Array.prototype.unshift

unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)

语法:arr.unshift(element1, ..., elementN)

Array.prototype.myUnshift = function () {
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let len = arguments.length;
this.length += len;
//注意要从后往前循环,防止后面的值都被覆盖为前面arguments的值
for (let i = this.length - 1; i >= 0; i--) {
//当i小于传入的参数时取传入的参数,否则取原先的值
this[i] = i < len ? arguments[i] : this[i - len];
}
return this.length;
};

8. Array.prototype.join

join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符

语法:arr.join([separator])

参数:separator 为可选,指定一个字符串来分隔数组的每个元素。如果需要,将分隔符转换为字符串。如果缺省该值,数组元素用逗号(,)分隔。如果separator是空字符串 (""),则所有元素之间都没有任何字符。

如果一个元素为 undefined 或 null,它会被转换为空字符串

  Array.prototype.myJoin = function (s = ',') {
if (!Array.isArray(this)) {
throw new TypeError('必须为数组才可调用此方法');
}
let str = '';
for (let i = 0; i < this.length; i++) {
//判断数组元素是否为undefined或null
if(this[i] === undefined || this[i] === null ) this[i] = ''
if (i === 0) str = `${this[i]}`;
else str = `${str}${s}${this[i]}`;
}
return str;
};

另外还有every、findIndex、includes、push等方法,实现比较简单便不做赘述

参考资料

JavaScript手写数组常用函数

Array MDN

JavaScript数组方法总结及手写的更多相关文章

  1. JavaScript数组方法大集合

    JavaScript数组方法集合 本文总结一下js数组处理用到的所有的方法.自己做个笔记. 数组方法 concat() 合并两个或多个数组 concat()能合并两个或者多个数组,不会更改当前数组,而 ...

  2. 一站式超全JavaScript数组方法大全

    一站式JavaScript数组方法大全(建议收藏) 方法一览表 详细操作 本人总结了JavaScript中有关数组的几乎所有方法(包含ES6之后新增的),并逐一用代码进行演示使用,希望可以帮助大家! ...

  3. JavaScript数组方法--every、some、fill

    接上一篇,JavaScript数组方法--concat.push,继续其他的数组方法. every:every() 方法测试数组的所有元素是否都通过了指定函数的测试. 先看其使用方法: functio ...

  4. 【译】你应该了解的JavaScript数组方法

    让我们来做一个大胆的声明:for循环通常是无用的,而且还导致代码难以理解.当涉及迭代数组.查找元素.或对其排序或者你想到的任何东西,都可能有一个你可以使用的数组方法. 然而,尽管这些方法很有用,但是其 ...

  5. JavaScript数组方法大全(推荐)

    原网址:http://www.jb51.net/article/87930.htm 数组在笔试中经常会出现的面试题,javascript中的数组与其他语言中的数组有些不同,为了方便之后数组的方法学习, ...

  6. JavaScript 数组方法处理字符串 prototype

    js中数组有许多方法,如join.map,reverse.字符串没有这些方法,可以“借用”数组的方法来处理字符串. <!doctype html> <html lang=" ...

  7. 2018.2.27 JavaScript数组方法应用

    JavaScript数组方法应用 1.找出元素item在给定数组arr中的位置 function indexOf(arr,item){ return arr.indexOf(item); } func ...

  8. JavaScript数组方法详解

    JavaScript数组方法详解 JavaScript中数组的方法种类众多,在ES3-ES7不同版本时期都有新方法:并且数组的方法还有原型方法和从object继承的方法,这里我们只介绍数组在每个版本中 ...

  9. JavaScript数组方法速查,32个数组的常用方法和属性

    JavaScript数组方法速查手册极简版 http://30ke.cn/doc/js-array-method JavaScript数组方法速查手册极简版中共收了32个数组的常用方法和属性,并根据方 ...

随机推荐

  1. 推荐 | Linux 思维导图整理(建议收藏)

    一个执着于技术的公众号 作者:小柑 来源:https://www.jianshu.com/p/59f759207862 今天整理了一下收集的 Linux 思维导图.上传的均为高清原图,双击即可查看,也 ...

  2. Spring Ioc源码分析系列--前言

    Spring Ioc源码分析系列--前言 为什么要写这个系列文章 首先这是我个人很久之前的一个计划,拖了很久没有实施,现在算是填坑了.其次,作为一个Java开发者,Spring是绕不开的课题.在Spr ...

  3. 如何使用 Javascript 将图标字体渲染为图片

    前言 在软件开发中肯定要用到图标,比如下图的 Groove 音乐中就用到了许多图标.一种获取这些图标的方法是把 Groove 音乐截个图,然后熟练地开启 Photoshop,开始抠图.这种方式很逊,效 ...

  4. Azure DevOps (十三) 通过Azure Devops部署一个Go的Web应用

    前几篇文章中,我们分别实现通过azure来部署.NET和Springboot的应用,今天我们来研究一下如何部署一套Go的Web应用上去. 文章配套视频专栏: https://space.bilibil ...

  5. 并查集——以nuist OJ P1648炼丹术为例

    并查集 定义:并查集是一种树形的数据结构,用于处理一些不相交集合的合并及查询问题 主要构成: 并查集主要由一个整型数组pre[]和两个函数find().join()构成. 数组pre[]记录了每个点的 ...

  6. swagger在线api文档搭建指南,用于线上合适么?

    在上一篇文章中,我们讲解了什么是 api,什么是 sdk: https://www.cnblogs.com/tanshaoshenghao/p/16217608.html 今天将来到我们万丈高楼平地起 ...

  7. c++:-9

    上节(c++:-8)主要学习了C++的流类库和输入输出,本节学习C++的异常处理. 异常处理 介绍 (1)异常处理的基本思想: (2)异常处理的语法: (3)举例:处理除0异常 #include &l ...

  8. Map和WeakMap的方法和区别

    Map Map是一组键值对的结构,具有极快的查找速度. 一.构造函数不同 let map = new Map(); let weakmap = new WeakMap(); 二.内置函数不同 Map的 ...

  9. Django序列化组件与数据批量操作与简单使用Forms组件

    目录 SweetAlert前端插件 Django自带的序列化组件 批量数据操作 分页器与推导流程 Forms组件之创建 Forms组件之数据校验 Forms组件之渲染标签 Forms组件之信息展示 S ...

  10. [CSP-S 2019 Day2]Emiya家今天的饭

    思路: 这种题目就考我们首先想到一个性质.这题其实容易想到:超限的菜最多只有一个,再加上这题有容斥那味,就枚举超限的菜然后dp就做完了. 推式子能力还是不行,要看题解. 式子还需要一个优化,就是废除冗 ...