• js手写数组Api--模拟实现常见数组Api


    数组的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)

    代码实现:
    Array.prototype._every = function (fn, thisValue) {
        let arr = thisValue || this // thisValue 有值 就以thisValue 为准
        if (typeof fn !== 'function') {
          throw new TypeError(fn + ' is not a function');
        }
        // 空数组 返回 true
        if (!arr.length) {
          return true
        }
        for (let i = 0; i < arr.length; i++) {
          if (!fn.call(this, arr[i], i, arr)) {
            return false
          }
        }
        return true
    }
    
    function checkAdult(item) {
      return item >= 11
    }
    
    let arr = [32, 33, 16, 40]
    let result = arr._every(checkAdult)
    console.log(result) // true

    Filter

    定义和用法:

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

    语法

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

    代码实现
    Array.prototype._filter = function (fn, thisValue) {
        let arr = thisValue || this
        let result = []
        if (typeof fn !== 'function') {
          throw new TypeError(fn + ' is not a function');
        }
        if (!arr.length) { // 空数组不处理 直接返回空数组
            return []
        }
        for (let i = 0; i < arr.length; i++) {
          if(fn.call(arr, arr[i], i, arr)) {
            result.push(arr[i])
          }
        }
        return result
    }
    
    let arr = [4, 9, 16, 25];
    let result = arr._filter((item) => {
        return item > 10
    })
    console.log(result) // [16, 25]

    Find

    定义和用法

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

    语法

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

    代码实现
    Array.prototype._find = function (fn, thisValue) {
      let arr = thisValue || this
        if (typeof fn !== 'function') {
        throw new TypeError(fn + ' is not a function');
      }
      if (!this.length) { // 空数组返回 undefined
        return undefined
      }
      for (let i = 0; i < arr.length; i++) {
        let result = fn.call(arr, arr[i], i, arr)
        if (result) {
          return arr[i]
        }
      }
      return undefined
    }
    
    let arr = [3, 10, 18, 20]
    function checkAdult(age) {
      return age > 11
    }
    let result = arr._find(checkAdult)
    console.log(result) // 18

    IndexOf

    定义和用法

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

    语法

    array.indexOf(item,start)

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

    ForEach

    定义和用法

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

    语法

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

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

    From

    定义和用法

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

    语法

    Array.from(object, mapFunction, thisValue)

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

    Includes

    定义和用法

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

    语法

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

    代码实现
    Array.prototype._includes = function (searchElement, fromIndex = 0) {
      let arr = this
      if (fromIndex >= arr.length || !arr.length){
        return false
      }
      for (let i = fromIndex; i < arr.length; i++) {
        if (arr[i] === searchElement) {
          return true
        }
      }
      return false
    }
    
    let arr = ['a', 'b', 'c', 'd']
    
    let result = arr._includes('b')
    console.log(result) // true

    isArray

    定义和用法

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

    语法

    Array.isArray(obj)

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

    Map

    定义和用法

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

    语法

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

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

    Reduce

    定义和用法

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

    语法

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

    代码实现
    Array.prototype._reduce = function (fn, initialValue) {
      let arr = this
        if (typeof fn !== 'function') {
        throw new TypeError(fn + ' is not a function');
      }
      if (!arr.length) {
        throw new TypeError('数组不能为空');
      }
      let result = initialValue || 0
      for (let i = 0; i < arr.length; i++) {
        result = fn.call(arr, result, arr[i], i, arr)
      }
      return result
    }
    
    let arr = [1, 2, 3, 4];
    function getSum(total, currentValue, currentIndex, arr) {
      return total + currentValue
    }
    let result = arr._reduce(getSum, 2)
    console.log(result) // 12

    Slice

    定义和用法

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

    语法

    array.slice(start, end)

    代码实现
    Array.prototype._slice = function (start, end) {
        let result = []
      for (let i = start; i < start + end; i++){
        result.push(this[i])
      }
      return result
    }
    
    let arr = ["Banana", "Orange", "Lemon", "Apple", "Mango"]
    let result = arr._slice(1, 3)
    
    console.log(result) // ["Orange", "Lemon", "Apple"]
    console.log(arr) // ["Banana", "Orange", "Lemon", "Apple", "Mango"]

    Splice

    定义和用法

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

    返回值

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

    语法

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

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

    Sort

    定义和用法

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

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

    语法

    array.sort(sortfunction)

    代码实现—冒泡排序
    Array.prototype._sort = function (func) {
      let array = this
     if (arr.length <= 1) { // 如果数组长度小于等于1无需判断直接返回即可 
          return arr
      }
      if (func == undefined) {
           for (let i = 0; i < array.length; i++) {
               for(let j = 0; j < array.length - i - 1; j++) {
                 let temp = ""
                 if (String(array[j]) > String(array[j + 1])) {
                    // 这是一种交换方式
                    temp= array[j + 1];
                    array[j+1]=array[j];
                    array[j]=temp;
                 }
               }
           }
       }
       else if (typeof func == "function") {
           for (let i = 0; i < array.length; i++) {
               for (let j = 0; j < array.length - i - 1; j++) {
                 let val = func(array[j], array[j + 1]);
                 if (val > 0) {
                   // 这也是一种交换方式
                   array[j] = array[j] + array[j + 1];
                   array[j + 1] = array[j] - array[j + 1];
                   array[j] = array[j] - array[j + 1];
                 }
               }
           }
       } else if (typeof func !== 'function') {
          throw new TypeError(func + ' is not a function');
      } 
      return array
     }
    代码实现—快速排序
    Array.prototype._sort = function (func) {
        let arr = this
        if (arr.length <= 1) { // 如果数组长度小于等于1无需判断直接返回即可 
          return arr
        }
      let pivotIndex = Math.floor(arr.length / 2) // 取基准点 
      let pivot = arr.splice(pivotIndex, 1)[0] // 取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数
      let left = [] // 存放比基准点小的数组
      let right = [] // 存放比基准点大的数组 
      for (let i = 0; i < arr.length; i++){ //遍历数组,进行判断分配 
        if (arr[i] < pivot) {
          left.push(arr[i]) // 比基准点小的放在左边数组 
        } else {
          right.push(arr[i]) // 比基准点大的放在右边数组 
        }
      }
         //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1; 
      return quickSort(left).concat([pivot], quickSort(right));
    }
    
     let arr1 = [4, 32, 2, 54]
     arr1.sort((a, b) => {
      return a - b
     })
     console.log(arr1) // [2, 4, 32, 54]
    
     let arr2 = [4, 32, 2, 54]
     arr2.sort()
     console.log(arr2) // [2, 32, 4, 54]
  • 相关阅读:
    个人知识管理系统Version1.0开发记录(09)
    个人知识管理系统Version1.0开发记录(08)
    个人知识管理系统Version1.0开发记录(07)
    个人知识管理系统Version1.0开发记录(06)
    个人知识管理系统Version1.0开发记录(05)
    个人知识管理系统Version1.0开发记录(04)
    登录流程
    小程序开发工具黑屏
    免费BOOTSTARP后台模板
    JQUERY重写
  • 原文地址:https://www.cnblogs.com/yalong/p/11606865.html
Copyright © 2020-2023  润新知