JavaScript数组方法总结及手写
文章首发: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数组方法总结及手写的更多相关文章
- JavaScript数组方法大集合
JavaScript数组方法集合 本文总结一下js数组处理用到的所有的方法.自己做个笔记. 数组方法 concat() 合并两个或多个数组 concat()能合并两个或者多个数组,不会更改当前数组,而 ...
- 一站式超全JavaScript数组方法大全
一站式JavaScript数组方法大全(建议收藏) 方法一览表 详细操作 本人总结了JavaScript中有关数组的几乎所有方法(包含ES6之后新增的),并逐一用代码进行演示使用,希望可以帮助大家! ...
- JavaScript数组方法--every、some、fill
接上一篇,JavaScript数组方法--concat.push,继续其他的数组方法. every:every() 方法测试数组的所有元素是否都通过了指定函数的测试. 先看其使用方法: functio ...
- 【译】你应该了解的JavaScript数组方法
让我们来做一个大胆的声明:for循环通常是无用的,而且还导致代码难以理解.当涉及迭代数组.查找元素.或对其排序或者你想到的任何东西,都可能有一个你可以使用的数组方法. 然而,尽管这些方法很有用,但是其 ...
- JavaScript数组方法大全(推荐)
原网址:http://www.jb51.net/article/87930.htm 数组在笔试中经常会出现的面试题,javascript中的数组与其他语言中的数组有些不同,为了方便之后数组的方法学习, ...
- JavaScript 数组方法处理字符串 prototype
js中数组有许多方法,如join.map,reverse.字符串没有这些方法,可以“借用”数组的方法来处理字符串. <!doctype html> <html lang=" ...
- 2018.2.27 JavaScript数组方法应用
JavaScript数组方法应用 1.找出元素item在给定数组arr中的位置 function indexOf(arr,item){ return arr.indexOf(item); } func ...
- JavaScript数组方法详解
JavaScript数组方法详解 JavaScript中数组的方法种类众多,在ES3-ES7不同版本时期都有新方法:并且数组的方法还有原型方法和从object继承的方法,这里我们只介绍数组在每个版本中 ...
- JavaScript数组方法速查,32个数组的常用方法和属性
JavaScript数组方法速查手册极简版 http://30ke.cn/doc/js-array-method JavaScript数组方法速查手册极简版中共收了32个数组的常用方法和属性,并根据方 ...
随机推荐
- 记将一个大型客户端应用项目迁移到 dotnet 6 的经验和决策
在经过了两年的准备,以及迁移了几个应用项目积累了让我有信心的经验之后,我最近在开始将团队里面最大的一个项目,从 .NET Framework 4.5 迁移到 .NET 6 上.这是一个从 2016 时 ...
- 【Python数据分析案例】python数据分析老番茄B站数据(pandas常用基础数据分析代码)
一.爬取老番茄B站数据 前几天开发了一个python爬虫脚本,成功爬取了B站李子柒的视频数据,共142个视频,17个字段,含: 视频标题,视频地址,视频上传时间,视频时长,是否合作视频,视频分区,弹幕 ...
- 微信新菜单类型 article_id 设置教程
前不久, Senparc.Weixin SDK 跟随微信更新的步伐,上线了新的素材管理接口,其中也涉及到了 article_id 类型的自定义菜单接口. 本文将演示如何使用新的菜单类型. 官方文档传送 ...
- 购物车+ATM项目(图形化)
项目下载 项目目录结构 运行效果 seetings.py import logging import logging.config # 定义日志输出格式 开始 import os standard_f ...
- 用python实现自动化登录禅道系统 设置定时器自动执行脚本
由于各种原因,我想试下用python实现自动登录禅道系统,并且每天定时执行.(本人第一次接触自动化,在大佬眼中门槛都没摸到的类型) 首先缕清思路: 1.实现自动登录禅道系统,用selenium实现2. ...
- Fail2ban 配置详解 配置说明
fail2ban的配置主要由基础配置(fail2ban.conf)和监禁配置(jail.conf)两部分组成. fail2ban的配置采用标签块"[块名]"和键值"key ...
- 声学感知刻度(mel scale、Bark scale、ERB)与声学特征提取(MFCC、BFCC、GFCC)
梅尔刻度 梅尔刻度(Mel scale)是一种由听众判断不同频率 音高(pitch)彼此相等的感知刻度,表示人耳对等距音高(pitch)变化的感知.mel 刻度和正常频率(Hz)之间的参考点是将1 k ...
- Unicode和中午互转
import java.io.UnsupportedEncodingException; public class TestUnicode{ /* * 中文转unicode编码 */ public s ...
- C语言 - 基础数据结构和算法 - 单向链表
听黑马程序员教程<基础数据结构和算法 (C版本)>,照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友可 ...
- 技术分享 | app自动化测试(Android)--App 控件定位
原文链接 客户端的页面通过 XML 来实现 UI 的布局,页面的 UI 布局作为一个树形结构,而树叶被定义为节点.这里的节点也就对应了要定位的元素,节点的上级节点,定义了元素的布局结构.在 XML 布 ...