数组的API经常用,但是api的内部实现还没研究过,于是就研究学习了下。

原文地址: https://www.cnblogs.com/yalong/p/11606865.html

数组的API的具体使用方看这里 API详细用法
本文记录了数组中的 every,filter, find , indexOf, forEach, from, includes, isArray, map, reduce,slice,splice, sort这些个API的实现,如有不当,欢迎指出。

Every

定义和用法:

every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
注意: every() 对空数组检测 返回 true。
注意: every() 不会改变原始数组。

语法

array.every(function(currentValue,index,arr), thisValue)

代码实现:
  1. Array.prototype._every = function (fn, thisValue) {
  2. let arr = thisValue || this // thisValue 有值 就以thisValue 为准
  3. if (typeof fn !== 'function') {
  4. throw new TypeError(fn + ' is not a function');
  5. }
  6. // 空数组 返回 true
  7. if (!arr.length) {
  8. return true
  9. }
  10. for (let i = 0; i < arr.length; i++) {
  11. if (!fn.call(this, arr[i], i, arr)) {
  12. return false
  13. }
  14. }
  15. return true
  16. }
  17.  
  18. function checkAdult(item) {
  19. return item >= 11
  20. }
  21.  
  22. let arr = [32, 33, 16, 40]
  23. let result = arr._every(checkAdult)
  24. console.log(result) // true

Filter

定义和用法:

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
注意: filter() 不会对空数组进行检测。
注意: filter() 不会改变原始数组。

语法

array.filter(function(currentValue,index,arr), thisValue)

代码实现
  1. Array.prototype._filter = function (fn, thisValue) {
  2. let arr = thisValue || this
  3. let result = []
  4. if (typeof fn !== 'function') {
  5. throw new TypeError(fn + ' is not a function');
  6. }
  7. if (!arr.length) { // 空数组不处理 直接返回空数组
  8. return []
  9. }
  10. for (let i = 0; i < arr.length; i++) {
  11. if(fn.call(arr, arr[i], i, arr)) {
  12. result.push(arr[i])
  13. }
  14. }
  15. return result
  16. }
  17.  
  18. let arr = [4, 9, 16, 25];
  19. let result = arr._filter((item) => {
  20. return item > 10
  21. })
  22. console.log(result) // [16, 25]

Find

定义和用法

find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。
find() 方法为数组中的每个元素都调用一次函数执行:
当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。
如果没有符合条件的元素返回 undefined
注意: find() 对于空数组,函数是不会执行的。
注意: find() 并没有改变数组的原始值。

语法

array.find(function(currentValue, index, arr),thisValue)

代码实现
  1. Array.prototype._find = function (fn, thisValue) {
  2. let arr = thisValue || this
  3. if (typeof fn !== 'function') {
  4. throw new TypeError(fn + ' is not a function');
  5. }
  6. if (!this.length) { // 空数组返回 undefined
  7. return undefined
  8. }
  9. for (let i = 0; i < arr.length; i++) {
  10. let result = fn.call(arr, arr[i], i, arr)
  11. if (result) {
  12. return arr[i]
  13. }
  14. }
  15. return undefined
  16. }
  17.  
  18. let arr = [3, 10, 18, 20]
  19. function checkAdult(age) {
  20. return age > 11
  21. }
  22. let result = arr._find(checkAdult)
  23. console.log(result) // 18

IndexOf

定义和用法

indexOf() 方法可返回数组中某个指定的元素位置。
该方法将从头到尾地检索数组,看它是否含有对应的元素。开始检索的位置在数组 start 处或数组的开头(没有指定 start 参数时)。如果找到一个 item,则返回 item 的第一次出现的位置。开始位置的索引为 0。
如果在数组中没找到指定元素则返回 -1。

语法

array.indexOf(item,start)

代码实现
  1. Array.prototype._indexOf = function (item, start = 0) {
  2. let arr = this
  3. for (let i = start; i < arr.length; i++) {
  4. if (item === arr[i]) {
  5. return i
  6. }
  7. }
  8. return -1
  9. }
  10.  
  11. let arr = ["Banana","Orange","Apple","Mango","Banana","Orange","Apple"];
  12. let result = arr._indexOf("Apple", 4)
  13. console.log(result) // 6

ForEach

定义和用法

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
注意: forEach() 对于空数组是不会执行回调函数的。

语法

array.forEach(function(currentValue, index, arr), thisValue)

代码实现
  1. Array.prototype._forEach = function (fn, thisValue) {
  2. let arr = thisValue || this
  3. if (typeof fn !== 'function') {
  4. throw new TypeError(fn + ' is not a function');
  5. }
  6. for (let i = 0; i < arr.length; i++) {
  7. fn.call(arr, arr[i], i, arr);
  8. }
  9. }
  10.  
  11. let arr = [4, 9, 16, 25];
  12. arr._forEach((item, i, arr) => {
  13. console.log('item:' + item + ' i: ' + i)
  14. })

From

定义和用法

from() 方法用于通过拥有 length 属性的对象或可迭代的对象来返回一个数组。
如果对象是数组返回 true,否则返回 false。

语法

Array.from(object, mapFunction, thisValue)

代码实现
  1. Array.prototype._from = function (object, mapFunction, thisValue) {
  2. let obj = thisValue || this
  3. let result = []
  4. // 没有length属性 或者 length 为0的 直接返回空数组
  5. if (!object.length) {
  6. return result
  7. }
  8. if (typeof object === 'string') {
  9. result = object.split('')
  10. } else {
  11. object.forEach(item => result.push(item))
  12. }
  13. if (typeof mapFunction !== 'function') {
  14. throw new TypeError(mapFunction + ' is not a function');
  15. }
  16. return result.map(mapFunction, thisValue)
  17. }
  18.  
  19. let r1 = Array.prototype._from([1, 2, 3], x => x * 10)
  20. console.log(r1) // [10, 20, 30, 40]
  21. let r2 = Array.prototype._from('1234', x => x * 10)
  22. console.log(r2) // [10, 20, 30]

Includes

定义和用法

includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

语法

arr.includes(searchElement)
arr.includes(searchElement, fromIndex)

代码实现
  1. Array.prototype._includes = function (searchElement, fromIndex = 0) {
  2. let arr = this
  3. if (fromIndex >= arr.length || !arr.length){
  4. return false
  5. }
  6. for (let i = fromIndex; i < arr.length; i++) {
  7. if (arr[i] === searchElement) {
  8. return true
  9. }
  10. }
  11. return false
  12. }
  13.  
  14. let arr = ['a', 'b', 'c', 'd']
  15.  
  16. let result = arr._includes('b')
  17. console.log(result) // true

isArray

定义和用法

isArray() 方法用于判断一个对象是否为数组。
如果对象是数组返回 true,否则返回 false。

语法

Array.isArray(obj)

代码实现
  1. Array.prototype._isArray = function (item) {
  2. // 只是判断数组用这个就够了
  3. // 判断数据类型最全面,最准确的方式是用 Object.prototype.toString.call(1)
  4. if(item.__proto__.constructor === Array) {
  5. return true
  6. } else {
  7. return false
  8. }
  9. }
  10.  
  11. let arr = [1, 2, 3, 4]
  12. console.log(Array.prototype._isArray(arr)) // true

Map

定义和用法

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组。

语法

array.map(function(currentValue,index,arr), thisValue)

代码实现
  1. Array.prototype._map = function (fn, thisValue) {
  2. let arr = thisValue || this
  3. let result = []
  4. if (typeof fn !== 'function') {
  5. throw new TypeError(fn + ' is not a function');
  6. }
  7. for (let i = 0; i < arr.length; i++) {
  8. let r = fn.call(arr, arr[i], i, arr)
  9. result.push(r)
  10. }
  11. return result
  12. }
  13.  
  14. let arr = [4, 9, 16, 25];
  15. let result = arr._map((item) => {
  16. return item * 2
  17. })
  18.  
  19. console.log(result) //[8, 18, 32, 50]
  20. console.log(arr) //[4, 9, 16, 25]

Reduce

定义和用法

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce() 可以作为一个高阶函数,用于函数的 compose。
注意: reduce() 对于空数组是不会执行回调函数的。

语法

array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

代码实现
  1. Array.prototype._reduce = function (fn, initialValue) {
  2. let arr = this
  3. if (typeof fn !== 'function') {
  4. throw new TypeError(fn + ' is not a function');
  5. }
  6. if (!arr.length) {
  7. throw new TypeError('数组不能为空');
  8. }
  9. let result = initialValue || 0
  10. for (let i = 0; i < arr.length; i++) {
  11. result = fn.call(arr, result, arr[i], i, arr)
  12. }
  13. return result
  14. }
  15.  
  16. let arr = [1, 2, 3, 4];
  17. function getSum(total, currentValue, currentIndex, arr) {
  18. return total + currentValue
  19. }
  20. let result = arr._reduce(getSum, 2)
  21. console.log(result) // 12

Slice

定义和用法

slice() 方法可从已有的数组中返回选定的元素。
slice()方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
注意: slice() 方法不会改变原始数组。

语法

array.slice(start, end)

代码实现
  1. Array.prototype._slice = function (start, end) {
  2. let result = []
  3. for (let i = start; i < start + end; i++){
  4. result.push(this[i])
  5. }
  6. return result
  7. }
  8.  
  9. let arr = ["Banana", "Orange", "Lemon", "Apple", "Mango"]
  10. let result = arr._slice(1, 3)
  11.  
  12. console.log(result) // ["Orange", "Lemon", "Apple"]
  13. console.log(arr) // ["Banana", "Orange", "Lemon", "Apple", "Mango"]

Splice

定义和用法

splice() 方法用于添加或删除数组中的元素。
注意:这种方法会改变原始数组。

返回值

如果仅删除一个元素,则返回一个元素的数组。 如果未删除任何元素,则返回空数组。

语法

array.splice(index,howmany,item1,.....,itemX)

代码实现
  1. Array.prototype._splice = function (index, howmany = 0) {
  2. let arr = this
  3. let left = arr.slice(0, index) // 截取左边的数组
  4. let right = arr.slice(index + howmany, arr.length) // 截取右边的数组
  5. let subArr = Array.prototype.slice.call(arguments, 2) // 截取参数里面需要添加的数组
  6. let result = []
  7. // 合并数组
  8. result = [...left, ...subArr, ...right]
  9. // 这里改变 this, 就是改变原数组
  10. for (let i = 0; i < result.length; i++) {
  11. this[i] = result[i]
  12. }
  13. // 返回删除的数据
  14. return this.slice(index, index + howmany)
  15. }
  16.  
  17. let arr = ["Banana", "Orange", "Lemon", "Apple", "Mango"]
  18. let result = arr._splice(2, 1, "sss", "xxx")
  19. console.log(result) // ["sss"]
  20. console.log(arr) // ["Banana", "Orange", "sss", "xxx", "Apple", "Mango"]

Sort

定义和用法

sort() 方法用于对数组的元素进行排序。
排序顺序可以是字母或数字,并按升序或降序。

默认排序顺序为按字母升序。
注意:当数字是按字母顺序排列时"40"将排在"5"前面。
使用数字排序,你必须通过一个函数作为参数来调用。
函数指定数字是按照升序还是降序排列。
注意: 这种方法会改变原始数组!。

语法

array.sort(sortfunction)

代码实现—冒泡排序
  1. Array.prototype._sort = function (func) {
  2. let array = this
  3. if (arr.length <= 1) { // 如果数组长度小于等于1无需判断直接返回即可
  4. return arr
  5. }
  6. if (func == undefined) {
  7. for (let i = 0; i < array.length; i++) {
  8. for(let j = 0; j < array.length - i - 1; j++) {
  9. let temp = ""
  10. if (String(array[j]) > String(array[j + 1])) {
  11. // 这是一种交换方式
  12. temp= array[j + 1];
  13. array[j+1]=array[j];
  14. array[j]=temp;
  15. }
  16. }
  17. }
  18. }
  19. else if (typeof func == "function") {
  20. for (let i = 0; i < array.length; i++) {
  21. for (let j = 0; j < array.length - i - 1; j++) {
  22. let val = func(array[j], array[j + 1]);
  23. if (val > 0) {
  24. // 这也是一种交换方式
  25. array[j] = array[j] + array[j + 1];
  26. array[j + 1] = array[j] - array[j + 1];
  27. array[j] = array[j] - array[j + 1];
  28. }
  29. }
  30. }
  31. } else if (typeof func !== 'function') {
  32. throw new TypeError(func + ' is not a function');
  33. }
  34. return array
  35. }
代码实现—快速排序
  1. Array.prototype._sort = function (func) {
  2. let arr = this
  3. if (arr.length <= 1) { // 如果数组长度小于等于1无需判断直接返回即可
  4. return arr
  5. }
  6.   let pivotIndex = Math.floor(arr.length / 2) // 取基准点
  7.   let pivot = arr.splice(pivotIndex, 1)[0] // 取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数
  8.   let left = [] // 存放比基准点小的数组
  9.   let right = [] // 存放比基准点大的数组
  10.   for (let i = 0; i < arr.length; i++){ //遍历数组,进行判断分配
  11.     if (arr[i] < pivot) {
  12.       left.push(arr[i]) // 比基准点小的放在左边数组
  13.     } else {
  14.       right.push(arr[i]) // 比基准点大的放在右边数组
  15.     }
  16.   }
  17. //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;
  18.   return quickSort(left).concat([pivot], quickSort(right));
  19. }
  20.  
  21. let arr1 = [4, 32, 2, 54]
  22. arr1.sort((a, b) => {
  23. return a - b
  24. })
  25. console.log(arr1) // [2, 4, 32, 54]
  26.  
  27. let arr2 = [4, 32, 2, 54]
  28. arr2.sort()
  29. console.log(arr2) // [2, 32, 4, 54]

js手写数组Api--模拟实现常见数组Api的更多相关文章

  1. 常见的JS手写函数汇总(代码注释、持续更新)

    最近在复习面试中常见的JS手写函数,顺便进行代码注释和总结,方便自己回顾也加深记,内容也会陆陆续续进行补充和改善. 一.手写深拷贝 <script> const obj1 = { name ...

  2. 原生html、js手写 radio与checkbox 美化

    原生html.js手写 radio与checkbox   美化 html <!DOCTYPE html> <html> <head> <meta charse ...

  3. 五四青年节,今天要学习。汇总5道难度不高但可能遇到的JS手写编程题

    壹 ❀ 引 时间一晃,今天已是五一假期最后一天了,没有出门,没有太多惊喜与意外.今天五四青年节,脑子里突然想起鲁迅先生以及悲欢并不相通的话,我的五一经历了什么呢,忍不住想说那大概是,父母教育孩子大声嚷 ...

  4. 轮播图--JS手写

    轮播图基本每个网站都会有,也有很多的JQuery插件可以用,这里是用JS代码写的. @{ Layout = null; } <!DOCTYPE html> <html> < ...

  5. js手写俄罗斯方块

    代码如下 html: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  6. 浅谈时钟的生成(js手写代码)

    在生成时钟的过程中自己想到布置表盘的写法由这么几种: 当然利用那种模式都可以实现,所以我们要用一个最好理解,代码有相对简便的方法实现 1.利用三角函数 用js在三角函数布置表盘的过程中有遇见到这种情况 ...

  7. 不借助jquery封装好的ajax,你能用js手写ajax框架吗

    不借助jquery封装好的ajax,你能手写ajax框架吗?最基础的ajax框架,一起来围观吧. .创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); ...

  8. js手写图片查看器(图片的缩放、旋转、拖拽)

    在做一次代码编辑任务中,要查看图片器.在时间允许的条件下,放弃了已经封装好的图片jq插件,现在自己手写js实现图片的缩放.旋转.推拽功能! 具体代码如下: <!DOCTYPE html> ...

  9. 浅谈时钟的生成(js手写代码)(非原创)

    在生成时钟的过程中自己想到布置表盘的写法由这么几种: 当然利用那种模式都可以实现,所以我们要用一个最好理解,代码有相对简便的方法实现 1.利用三角函数 用js在三角函数布置表盘的过程中有遇见到这种情况 ...

随机推荐

  1. PAT Basic 1059 C语言竞赛 (20 分)

    C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛.既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽: 0.冠军将赢得一份“神秘大奖”(比如很巨大的一本学生研究论文集……). 1.排名为素数的学生将 ...

  2. 图像处理---《在图片上打印文字 putText()》

    图像处理---<在图片上打印文字 putText()> 目的:想在处理之后的图像上打印输出结果. 方法: (1)只在图像上打印 数字.字母的话:                 1.Mat ...

  3. C#信号量(Semaphore,SemaphoreSlim)

    Object->MarshalByRefObject->WaitHandle->Semaphore 1.作用: 多线程环境下,可以控制线程的并发数量来限制对资源的访问 2.举例: S ...

  4. BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]

    基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...

  5. DTcmsV4.0分析学习——(3)URL重写

    3.URL重写 3.1 控制流程 通过IHttpModule控制所有页面请求,具体流程如下 (1)真实路径可正常访问 (2)前台页面通过URL重写映射aspx目录,后台页面通过URL重写映射admin ...

  6. NativeRenderingPlugin IOS

    https://bitbucket.org/Unity-Technologies/graphicsdemos/src/77f014c12161e5c25d902e2c5697dd0c45ce3e35/ ...

  7. hbase实践之HFile结构

    本文目录如下所示: 目录 HFile在HBase架构中的位置 什么是HFile HFile逻辑结构 HFile逻辑结构的优点 HFile物理结构 HFile生成流程 HFile中Block块解析 多大 ...

  8. pandas中DataFrame和Series的数据去重

    在SQL语言中去重是一件相当简单的事情,面对一个表(也可以称之为DataFrame)我们对数据进行去重只需要GROUP BY 就好. select custId,applyNo from tmp.on ...

  9. Hivesql中的正则

    ================================================================================================= 一般 ...

  10. struts2之单文件上传(7)

    前台页面jsp <!-- 拦截的时候用这个 <s:form action="uploadAction" enctype="multipart/form-dat ...