深入 JS 中 Array 数组上方法的使用与实现原理(数组几乎所有的方法使用与对应实现)

Array

at

接收一个索引值,返回对应的元素(允许正数与负数,负数由最后一个元素开始倒数)

基本使用:

    const arr = ['a','b','c','d']
    arr.at(0) // a
    arr.at(-1) // d

at方法实现:

/**
 * 接收一个索引值,返回对应的元素(索引值为负数时,从后面倒数【如-1就为最后一个】)
 */
Array.prototype.at_k = function (index){ // 接收索引值
    var len = this.length // 存储调用者的长度
    if(index>=0){ // 接收的索引为正数时,直接返回对应索引的元素
        return this[index]
    }else{ // 接收的索引为负数时,返回长度加上索引值对应的元素【相当于从后面倒数】
        return this[len+index]
    }
}

concat

concat 方法用于合并两个或多个数组(不会更改现有数组,返回一个新数组 )

基本使用:

// 合并两个或多个数组
    const arr1 = [1,2,3]
    const arr2 = [10,20,30]
    const arr3 = [100.200,300]
    const arr4 = arr1.concat(arr2,arr3) // [1,2,3,10,20,30,100,200,300]

concat方法实现【合并多个数组】:

/**
 * 合并两个或多个数组,当合并数组只有本身的话,只会返回该引用值(即浅克隆)
 */
Array.prototype.concat_k = function(){
    if(arguments.length === 0){ // 判断调用该方法的参数,如果存在本身(没有参数),直接返回该引用值
        return this
    }else{
        if(Object.prototype.toString.call(this) !== '[object Array]'){ // 这个可以不需要,因为使用数组方法时,它会自动判断调用者是否为数组的
            throw new TypeError(`${this}.concat_k is not a function`)
        }else{
            let newArr = [] // 返回一个新数组(storageSpace)
            this.forEach(item => { // 先将方法调用的数组传入新数组
                newArr.push(item)
            })
            for(let i=0;i<arguments.length;i++){ // 将参数依次的克隆给新数组
                if(Object.prototype.toString.call(arguments[i]) === '[object Array]'){ // 参数是否为数组类型,将参数中的每一个值都克隆给新数组(合并到新数组)
                    arguments[i].forEach(element => {
                        newArr.push(element)
                    })
                }else{ // 参数不是数组类型,直接将该 value 合并到数组之中
                    newArr.push(arguments[i])
                }
            }   
            return newArr // 执行结束,返回一个新数组
        }
    }
}

copyWinthin

方法将数组元素复制到数组中的另一个位置,覆盖现有值 - 方法永远不会向数组添加更多项(会覆盖原始数组) - 不会改变原数组的长度

基本使用:

/**基本语法:  array.copyWithin(target, start, end)
*   target  -  将元素复制到的索引位置(必须)
*   start   -  开始复制元素的索引位置,默认为 0(可选)
*   end     -  停止从中复制元素的索引位置,默认为 array.length(可选)
*/

const arr =  [1,2,3,4,5]
    // 下面 3 条语句,都是单独运行的结果
    console.log(arr.copyWithin(2)) // 将元素复制到数组索引2的位置 - start为默认0,end为默认arr.length --> [1,2,1,2,3]
    console.log(arr.copyWithin(2,3)) // 将元素复制到数组索引2的位置 - start为3,end为默认arr.length --> [1,2,4,5,5]
    console.log(arr.copyWithin(2,3,4)) // 将元素复制到数组索引2的位置 - start为3,end为4 --> [1,2,4,4,5]

copyWinthin方法实现(数组浅复制):

// 第一版(已有更好的版本)
    Array.prototype.copyWithin_k = function (target,start,end){
        var starCount = 0,endCount = this.length - 1
        if(arguments === 1){
            for(let i=target;i<this.length;i++){
                this[i] = this[starCount]
                starCount ++
                if(starCount >= endCount){
                    break
                }
            }
        }else if(arguments === 2){
            starCount = start
            for(let i=target;i<this.length;i++){
                this[i] = this[starCount]
                starCount ++
                if(starCount >= endCount){
                    break
                }
            }
        }else if(arguments === 3){
            starCount = start
            endCount = end 
            for(let i=target;i<this.length;i++){
                this[i] = this[starCount]
                starCount ++
                if(starCount >= endCount){
                    break
                }
            }
        }
        return this
    }


// 第二版(优化版本)- (已有更高的版本)
    // 该版本,相较于第一版有着更高的可复用性、代码更为简洁、更方便阅读(减少了过多不必要的重复性代码)
    Array.prototype.copyWithin_k = function (target,start,end){
        function copyPackaging (target,start,end){ // 封装一个浅复制函数
            let starCount = start || 0  // 当存在参数时就使用参数,不存在参数就使用默认值
            let endCount = end || this.length - 1 
            for(let i=target;i<this.length;i++){ // 循环浅复制
                this[i] = this[starCount]
                starCount ++
                if(starCount >= endCount){ // 中断浅复制
                    break
                }
            }
        }
        copyPackaging(target,start,end) // 将调用该方法传入的参数,传入封装好的函数,该函数会自行判断是否使用默认值
        return this
    }


// 第三版(优化版本)
    // 该版本,相较于第二版,减少了中断语句部分,使代码执行效率略微提升
    Array.prototype.copyWithin_k = function (target,start,end){
        function copyPackaging (target,start,end){
            let starCount = start || 0 , endCount = end || this.length - 1 // 定义开始与结束位置的计数变量
            for(let i=target;i<=endCount;i++){ // 将循环解结束的条件,直接加在循环体中(这样就可以减少中断语句的判断)
                this[i] = this[starCount]
                starCount ++
            }
        }
        copyPackaging(target,start,end)
        return this
    }

entries

返回一个新的数组迭代器对象,该对象包含数组中每个索引的键/值对

基本使用:

// 生成迭代器,该迭代器中每一个迭代内容,都有对应的done,(当内容不为空时,属性值为true [当已经迭代完了,即没有属性值(undefined)]该属性值为false)
const arr = ['a','b','c','d']
const arrEntrises = arr.entries() // 返回一个可迭代对象,面分别存有数组中的每一个元素的索引与值,分别为对象的键值对
console.log(arrEntrises.next().value) // 返回的克爹带对象中,有一个next方法,表示下一个(里面有一个value属性,存放着该迭代对象的每一个键值对)
// 一位是可迭代对象,所以自然就能使用 for.. 进行遍历如
for(let element of arrEntrises){
    console.log(element) // 数组,里面存有索引与value
}
for(let [index,value] of arrEntrises){ // 分别将遍历的每一个元素,进行遍历
    console.log(index)
    console.log(value)
}

every

判断一个数组中的所有元素,是否都能通过某一个指定函数的测试

基本使用:

/**
 * every方法 - 测试一个数组内的所有元素是否都能通过某个指定函数的测试 - 返回一个布尔值
 *             整个数组都通过某一个指定的函数测试后,返回true - 反之false
 * every(callback) - 里面传入的时一个回调函数 - 并且该回调函数可以接收三个参数,分别为:元素值,元素的索引,原数组
        1.element - 用于测试的当前值
        2.index - 用于测试的当前索引值
        3.array - 调用的当前数组
    every方法的第二个参数 - thisArg - 执行 时使用的 thsi值(即callback调用时的this指向)
 */
    const arr = [1,2,3,4] // 检测数组
    const judge_number_1 = value => value>0 // 检测方法 - 判断数组是否所有元素都大于0
    const judge_number_2 = value => value>3 // 检测方法 - 判断数组是否所有元素都大于3
    console.log(arr.every(judge_number_1)) // 输出检测结果 - true
    console.log(arr.every(judge_number_2)) // 输出检测结果 - false

// 三个参数的接收与基本使用
    function isBigEnough(element, index, array) {
        console.log(index) // 输出当前索引值
        return element >= 10
    }
    console.log([12, 5, 8, 130, 44].every(isBigEnough)) // 0 1 false
    console.log([12, 54, 18, 130, 44].every(isBigEnough)) // 0 1 2 3 4 true

every方法实现 - 返回一个Boolean值:

/**主要功能
* 1.every方法传入的参数为一个回调函数(callback)
* 2.测试数组是否都能通过某一个回调函数的测试... (测试返回值的内容)
* 3.当数组中的所有元素都为true,返回true -- 但存在一个或多个为false,返回false
* 4.当调用该方法的数组为一个空数组,默认返回true
* 5.测试函数返回的时undefined时,默认为false
* .......
*/
    Array.prototype.every_k = function (callback,thisArg){ // 传入一个测试回调函数
        thisArg = thisArg || undefined
        for(let i=0;i<this.length;i++){ // 遍历整个数组
            let state = callback.call(thisArg,this[i],i,this) // 回调函数接收三个参数 + 方法的第二个参数thisArg执行时的callback this
            if(!state){ // 判断是否存在false,存在false,直接返回false - 反之返回true(都不存在false)
                return false
            }
        }
        return true
    }

fill

用一个固定值填充一个数组中从起始索引到终止索引内的全部元素,不包括终止索引 - 会改变原数组,但不会改变原数组的长度

基本使用:

/**fill方法 - 使用一个固定值填充一个数组的自定的起始位置到终止位置(不包括终止索引) -  会改变原数组,但不会改变原数组的长度
 *     1.fill方法中有三个参数,分别未:固定值、起始索引、终止索引
 *     2.当fill没有参数时,固定值会默认未undefined
 *     3.起始位置为数组的索引0处,终止索引为数组的长度(因为是不包括终止索引本身,所以是数组的长度而不是数组最大索引值)
 */
    const arr = [1,2,3,4];
    console.log(arr.fill('a',2,3)) // [ 1, 2, 'a', 4 ]
    console.log(arr) // [ 1, 2, 'a', 4 ]

    // .............................

基本实现:

/**fill方法实现
 *  使用一个固定值填充一个数组的自定的起始位置到终止位置
 */
    Array.prototype.fill_k = function (value,start,end){
        function fill_execute(value,start,end){
            let fill_value = value || undefined, // 判断函数的参数是否有值,如果没有值的情况下,使用默认值
                fill_start = start || 0,
                fill_end = end || this.length
            for(let i=fill_start;i<fill_end;i++){
                this[i] = fill_value // 因为这里使用了this,且函数本身也有自己的this - 所以在调用该函数时,需要绑定this(call、bind、apply)
            }
        }  
        fill_execute.call(this,value,start,end) // 调用时绑定this
        return this
    }

filter (过滤、过滤器)

创建给定数组一部分的浅拷贝,其包含通过所提供函数实现的测试的所有元素(与every方法相似,返回值不同)

相当于是测试某一个数组中的元素是否可以通过某一个回调函数的测试,会返回一个数组,该数组包含所用通过该函数测试的元素

基本使用:

/** filter方法基本使用 - 与every方法相似
 * filter方法 - 测试一个数组内的所有元素能通过某个指定函数的测试 - 返回一个数组,里面存放在所有通过测试的元素
 *             
 * filter(callback) - 里面传入的时一个回调函数 - 并且该回调函数可以接收三个参数,分别为:元素值,元素的索引,原数组 (与every方法一致)
        1.element - 用于测试的当前值
        2.index - 用于测试的当前索引值
        3.array - 调用的当前数组
    filter方法的第二个参数 - thisArg - 执行 时使用的 thsi值(即callback调用时的this指向)
 */
    const words = ['spray', 'limit', 'elite', 'exuberant', [1,2,3,4,5,6,7,8], 'present']
    const result = words.filter(word => word.length > 6)
    // 因为时浅克隆,所以在克隆引用值时为一个弱引用(引用地址)
        console.log(result)     //  Array ["exuberant", Array [1, 2, 3, 4, 5, 6, 7, 8], "present"]
        words[4][0] = 'kong'    // 改变原数组中的非原始值的value值
        console.log(result)     // Array ["exuberant", Array ["kong", 2, 3, 4, 5, 6, 7, 8], "present"]
        console.log(words)      // ["spray", "limit", "elite", "exuberant", Array ["kong", 2, 3, 4, 5, 6, 7, 8], "present"]

方法实现:

/**filter方法实现
 *  创建给定数组一部分的浅拷贝,其包含通过所提供函数实现的测试的所有元素
 *  当callback的返回值或element为undefined时,返回的是一个空数组(数组中的元素没有一个通过函数的测试时,也是返回一个空数组)
 */

/**主要功能
* 1.filter方法传入的参数为一个回调函数(callback)
* 2.测试数组哪一些能通过某一个回调函数的测试... (测试返回值的内容)
* 3.当数组中的所有元素都测试完时,将通过测试的元素 浅克隆 一份(返回该浅克隆)
* 5.测试函数返回的时undefined时,默认返回一个空数组
* .......
*/
    Array.prototype.filter_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let pass_storage = []
        for(let i=0;i<this.length;i++){
            let state = callback.call(thisArg,this[i],i,this) // 回调函数接收三个参数 + 方法的第二个参数thisArg执行时的callback this
            if(state){ // 判断测试是否通过,通过的元素浅克隆到 pass_storage中
                pass_storage.push(this[i])
            }
        }
        return pass_storage
    }

find

1.find

返回数组中满足提供的测试函数的第一个元素的值 – 否则返回 undefined

基本使用:

/** find方法基本使用
 * find方法 - 测试一个数组内的第一个能通过某个指定函数的测试的元素 - 返回一个该元素  --  若都不通过,则返回undefined
 *             
 * find(callback) - 里面传入的时一个回调函数 - 并且该回调函数可以接收三个参数,分别为:元素值,元素的索引,原数组 (与every方法一致)
        1.element - 用于测试的当前值
        2.index - 用于测试的当前索引值
        3.array - 调用的当前数组
    find方法的第二个参数 - thisArg - 执行 时使用的 thsi值(即callback调用时的this指向)
 */
    function test(element,index,Array){
        return element > 5
    }
    const arr = [1,2,3,4,5,6,7,8,9]
    console.log(arr.find(test)) // 6 - 返回第一个通过测试的元素
    // 查找数组中的对象......

// 必须有回调函数的参数,否则抛出错误

方法实现:

/**find方法实现
 *  返回数组中满足提供的测试函数的第一个元素的值  --  否则返回 undefined
 */
    Array.prototype.find_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let state = false
        for(let i=0;i<this.length;i++){
            state = callback.call(thisArg,this[i],i,this)
            if(state){
                return this[i]
            }
        }
        return undefined
    }

2.findIndex

基本使用:

    const arr = [1,2,3,4,5,6]
    function test(element){
        return element === 4
    }
    console.log(arr.findIndex(test)) // 3

方法实现:

/**findIndex方法实现 - 与find一样,只需将返回值改为索引值即可
 *  返回数组中满足提供的测试函数的第一个元素的索引  --  否则返回 -1
 */
    Array.prototype.find_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let state = false
        for(let i=0;i<this.length;i++){
            state = callback.call(thisArg,this[i],i,this)
            if(state){
                return i
            }
        }
        return -1
    }

3.findLast

方法返回数组中满足提供的测试函数条件的最后一个元素的值 - 如果没有找到对应元素,则返回 undefined

基本使用:

// 与find一样,只是一个为最先,一个为最后
    const arr = [1,2,3,4,5,6]
    function test(element){
        return element > 4
    }
    console.log(arr.findLast(test)) // 6

方法实现:

/**findLast方法实现
 *  返回数组中满足提供的测试函数条件的最后一个元素的值  --  否则返回 undefined
 *  这里与前面的find相反,即只需将遍历的顺序改为从后至前即可
 */
    Array.prototype.findLast_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let state = false
        for(let i=this.length-1;i>=0;i--){
            state = callback.call(thisArg,this[i],i,this)
            if(state){
                return this[i]
            }
        }
        return undefined
    }

4.findLastIndex

基本使用:

// 与findIndex一样,只是一个为最先,一个为最后
    const arr = [1,2,3,4,5,6]
    function test(element){
        return element > 4
    }
    console.log(arr.findLastIndex(test)) // 5 - 最后通过测试的索引

方法实现:

/**findLastIndex方法实现
 *  返回数组中满足提供的测试函数条件的最后一个元素的索引值  --  否则返回 -1
 *  这里与前面的findIndex相反,即只需将遍历的顺序改为从后至前即可
 */
    Array.prototype.findLastIndex_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let state = false
        for(let i=this.length-1;i>=0;i--){
            state = callback.call(thisArg,this[i],i,this)
            if(state){
                return i
            }
        }
        return -1
    }

flat and flatMap

flat

方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回(默认深度为1)

基本使用:

// 语法  --  flat()  -  flat(depth)
    // 默认深度 1
        var arr1 = [1, 2, [3, 4]];
        arr1.flat();
        // [1, 2, 3, 4]
        var arr2 = [1, 2, [3, 4, [5, 6]]];
        arr2.flat();
        // [1, 2, 3, 4, [5, 6]]
    // 使用指定深度
        var arr3 = [1, 2, [3, 4, [5, 6]]];
        arr3.flat(2);
        // [1, 2, 3, 4, 5, 6]

    //使用 Infinity,可展开任意深度的嵌套数组 - 无穷深度
        var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
        arr4.flat(Infinity);
        // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

基本实现:

/**flat方法实现(flat-平的)  ---  (相当于是深克隆,不过可以指定克隆的深度)
 *  按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
 *  并且flat方法会移除数组中的空项 - 即返回的新数组中不会保留空项
 *  可以理解为是数组降维,可定降维深度(deep),默认深度为1
 */
    Array.prototype.flat_k = function (deep){
        let storage_newArr = [], // 定义返回该递归数组的数组存储空间
            state = true // 定义降维的深度,当deep为Infinity是为true - 即深度为最深(即深克隆)
        if(deep === Infinity){ // 判断数组的deep是否为Infinity
            clone(this,storage_newArr,state)
        }else{ 
            state = deep || 1 // 当数组的deep不是Infinity时,将state转换成指定的深度(默认深度为1)
            clone(this,storage_newArr,state)
        }
        function clone(origin,target,state){ // 递归克隆封装
            let strArr = '[object Array]' // 用于判断数组中的值是为引用数组类型
            if(Object.prototype.toString.call(origin) === strArr){ // 判断origin是否为数组类型,不是数组类型(抛出错误)
                origin.forEach(item => {
                    if(Object.prototype.toString.call(item) === strArr){
                        if(state>0){ // 执行深度判读
                            state-- // 递归执行深度
                            clone(item,target,state)
                        }else{ // 当超出执行深度时,直接执行浅克隆(即不再执行降维操作)
                            target.push(item)
                        }
                    }else{ // 非数组类型,无需执行降维操作
                        target.push(item)
                    }
                })
            }else{
                throw TypeError('Type not array of origin')
            }
        }
        return storage_newArr
    }

flatMap

方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 连着深度值为 1 的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些

flatMap只能扁平一个维度(深度1),里面传入一个会调函数(与every相似)

基本使用:

// 基本操作如下
    const arr = [1,2,[10,20,30]]
    console.log(arr.flatMap(num => num*2)) // [ 2, 4, NaN ] // 数组中的每一个元素都会调用该回调函数
    function callback(element,index,array){ // 该回调函数的三个参数 => 正在执行的函数、正在执行元素的索引、正在执行的数组对象(与every等一样)
        return element === 10
    }
    console.log(arr.flatMap(callback)) 

基本实现:

/**flatMap方法实现
 *  返回一个新数组,该新数组中的每一个元素都是每个回调函数执行的返回值
 */
    Array.prototype.flatMap_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let storage_newArr = []
        for(let i=0;i<this.length;i++){
            let element = callback.call(thisArg,this[i],i,this)
            // 该语句用于判断是否返回的元素是否为一个空数组(若是空数组,不会保留到新数组中,即在新数组中删除该i元素)
            if(!(Object.prototype.toString.call(element) === '[object Array]' && element.length === 0)){
                storage_newArr.push(element)
            }
        }
        return storage_newArr
    }

forEach

方法对数组的每个元素执行一次给定的函数

基本使用

/**forEach方法会依次的遍历数组中的每一个元素,并且每一个元素都会调用回调函数
 *  回调函数(callback)中有单个参数分别为:正在执行的元素,正在执行元素的索引,遍历的数组对象
 *  该方法还可以有第二个回调函数,thisArg - 表示callback的this执行绑定
 *  基本使用如下
 */
    const arr = [1,2,3]
    arr.forEach(item => { // 这里可以接收3个参数
        console.log(item) // 会执行3遍该回调函数,反别输出 1 2 3
    })

方法实现

/**forEach方法实现
 *  1.遍历数组中的每一个元素,并且每一个元素都执行一次该方法的回调函数(回调函数可接收3个参数,后两个可选)
 *  2.该方法除了可以有回调函数的参数外,还有个可选的thisArg参数(表示该回调函数的this指向的绑定,默认为undefined)
 */
    Array.prototype.forEach_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        for(let i=0;i<this.length;i++){
            callback.call(thisArg,this[i],i,this)
        }
    }

Array.from

Array.from() 静态方法从可迭代或类似数组的对象创建一个新的、浅拷贝的实例

基本使用

/**Array.from() 静态方法
 *  1.里面可传入3个参数:一个为可迭代类、数组、一个为回调函数(该回调函数会在第一个参数的迭代中多次执行)、一个为thisArg(callback的this指向) - 【静态方法】
        (1)arrayLike  --  要转换为数组的可迭代或类似数组的对象
        (2)mapFn  --  回调函数(可选)
        (3)thisArg  --  this指向(可选)
 *  2.该回调函数中的参数只有两个:正在执行的元素与索引
 */
    function aa(a,b,c){
        console.log(a)
        console.log(b)
        console.log(c)
    }
    const arr = [1,2,3]
    console.log(Array.from(arr,aa))

// 更多使用方法与基本使用场景(参考文档)

基本实现

/**Array.from() 静态方法实现
 *  1.里面可传入3个参数:一个为可迭代类、数组、一个为回调函数(该回调函数会在第一个参数的迭代中多次执行)、一个为thisArg(callback的this指向) - 【静态方法】
        (1)arrayLike  --  要转换为数组的可迭代或类似数组的对象
        (2)mapFn  --  回调函数(可选)
        (3)thisArg  --  this指向(可选)
 *  2.该回调函数中的参数只有两个:正在执行的元素与索引
 */
    Array.from_k = function(arrLike,callback,thisArg){
        let storage_newArr = []
        for(let i=0;i<arrLike.length;i++){
            storage_newArr.push(callback.call(thisArg,arrLike[i],i))
        }
        return storage_newArr
    }

includes

确定数组是否 在其条目中包含一定的值,返回或酌情返回。truefalse

可以理解为是判断数组中是否包含某一个值,返回true或false

基本使用

/**includes方法(包含) -  用于判断数组中是否包含某一个元素
 *  1.该方法有两个参数:
        (1)searchElement - 所要判断的元素
        (2)fromIndex - 从数组中指定索引处开始搜索(默认从头到尾)
    2.fromIndex:
        (1)默认搜索整个数组
        (2)如果为负数,会先从会往前数但对应的索引后,再次往后搜索
        (3)如果该值超出数组的长度 -- false
 */
    const arr = [1,2,3]
    console.log(arr.includes(2)) // true
    console.log(arr.includes(2,2)) // false
    console.log(arr.includes(2,-3)) // true  --  因为该处是-3,即是该数组中的第一个元素(一样是从前往后数)

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**include方法(包含) -  用于判断数组中是否包含某一个元素
 *  1.该方法有两个参数:
        (1)searchElement - 所要判断的元素
        (2)fromIndex - 从数组中指定索引处开始搜索(默认从头到尾)
    2.fromIndex:
        (1)默认搜索整个数组
        (2)如果为负数,会先从会往前数但对应的索引后,再次往后搜索
        (3)如果该值超出数组的长度 -- false
 */
    Array.prototype.includes_k = function (searchElement,fromIndex){
        // parseInt - 如果输入的索引值为小数是,将其转换成整数
        fromIndex = parseInt(fromIndex) || 0 // 判断是否指定开始索引
        fromIndex = parseInt(fromIndex)<0? fromIndex+this.length : fromIndex // 判断是否为负数,若为负数就需从后往前数(可直接使用 负数值+迭代对象的长度)
        for(let i=fromIndex;i<this.length;i++){
            if(searchElement === this[i]){ // 判断数组是否存在对应的元素
                return true
            }
        }
        return false
    }

indexOf

返回第一个索引,其中 给定元素可以在数组中找到,如果不存在,则为 -1 (即默认返回第一个搜索到的索引)

基本使用

    const arr = [1,2,3,2,4]
    console.log(arr.indexOf(2))
    console.log(arr.indexOf(2,2))

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**indexOf方法
 *  1.该方法有两个参数:
        (1)searchElement -- 所要搜索的的元素
        (2)fromIndex -- 从零开始搜索的索引,转换为整数
    2.该方法返回索引值

    该方法与includes方法基本一样,只不过返回值不同而已
 */
    Array.prototype.indexOf_k = function (searchElement,fromIndex){
        fromIndex = parseInt(fromIndex) || 0
        fromIndex = parseInt(fromIndex)<0? fromIndex+this.length : fromIndex
        for(let i=fromIndex;i<this.length;i++){
            if(searchElement === this[i]){ 
                return i
            }
        }
        return -1
    }

lastIndexOf

与indexOf一样,不同的是该方法返回的是最后一个找到的索引值

基本使用:

// 该方法相当于是从后往前数
    const arr = [1,2,3,2,4]
    console.log(arr.lastIndexOf(2)) // 3
    console.log(arr.lastIndexOf(2,2)) // 1

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**lastIndexOf方法
 *  该方法与indexOf方法一样,不过是返回最后一个找到的索引值(即可以使用从后往前数的方式)
 */
    Array.prototype.lastIndexOf_k = function (searchElement,fromIndex){
        fromIndex = parseInt(fromIndex) || this.length-1 // 因为该方法是从后往前数,所以该方法的默认值为最后一位值this.length-1
        fromIndex = parseInt(fromIndex)<0? fromIndex+this.length : fromIndex
        for(let i=fromIndex;i>=0;i--){
            if(searchElement === this[i]){ 
                return i
            }
        }
        return -1
    }

join(连接)

连接数组中的所有元素返回新字符串 (或类似数组的对象) – 可指定分隔符(默认为逗号)

基本使用

/**join方法(连接)
 *  1.该方法会遍历数组会类数组中的每一个值,并将其连接成一个新的字符串
 *  2.连接成字符串的连接符可自定,在该方法的参数中指定
 *  3.基本使用如下
 */
    // 数组的使用
        const arr = ['kong','xiang','huang']
        console.log(arr.join()) // kong,xiang,huang - 默认逗号连接符
        console.log(arr.join('-')) // kong-xiang-huang - 自定连接符
        console.log(arr.join(' ')) // kong xiang huang - 自定连接符

    // 类数组的使用
        const arr_class = {
            length:3,
            0:'wang',
            1:'shen',
            2:'ou',
        }
        /**
         * 因为是类数组而不是真正的数组类型,所以无法直接使用该方法
         * 只能将该方法写出来,通过call将this绑定到该类数组中 - 后面解为join方法的参数
         */
        const str = Array.prototype.join.call(arr_class,'-')
        console.log(str) // wang-shen-ou


// 更多使用方法与基本使用场景(参考文档)

基本实现

/**join方法(连接)
 *  1.该方法会遍历数组会类数组中的每一个值,并将其连接成一个新的字符串
 *  2.连接成字符串的连接符可自定,在该方法的参数中指定
 */
    Array.prototype.join_K = function (separator){
        separator = separator || ','
        let retStr = ''
        function execute_join(separator){ // 使用封装函数,使其可以指定this指向 - 使其类数组也可以连接操作
            for(let i=0;i<this.length;i++){
                this[i] = this[i] || ''
                if(i===this.length-1){
                    retStr += this[i]
                }else{
                    retStr += this[i] + separator
                }
                
            }
        }
        execute_join.call(this,separator) 
        return retStr
    } 

keys

返回一个新的数组 包含数组中每个迭代器对象的索引/键值

基本使用

    const array1 = ['a', 'b', 'c'];
    const iterator = array1.keys();
    for (const key of iterator) {
        console.log(key);
    }
    // Expected output: 0
    // Expected output: 1
    // Expected output: 2


// 更多使用方法与基本使用场景(参考文档)

借本实现

/**keys方法(获取数组索引) - 返回一个新数组
 *  
 */
    Array.prototype.keys_k = function (){
        let space_storage = []
        function execute_keys(){
            for(let i=0;i<this.length;i++){
                space_storage.push(i)
            }
        }
        execute_keys.call(this)
        return space_storage
    }

map

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

基本使用

    const arr = [1,2,3]
    console.log(arr.map(n => n*2)) // [2,4,6]
    console.log(arr.map(n => undefined)) // [undefined,undefined,undefined]

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**map方法
 *  0.创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
 *  1.该方法有两个参数:
        (1)callback - 回调函数
        (2)thisArg - callback的this指向
    2.callback中可以接收3个参数:
        (element) - 正在执行的元素
        (index) - 正在执行元素的索引
        (array) - 正在执行的数组对象
 */
    Array.prototype.map_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        let newArr = []
        function execute_map(){
            for(let i=0;i<this.length;i++){
                newArr.push(callback.call(thisArg,this[i],i,this))
            }
        }
        execute_map.call(this)
        return newArr
    }

reduce

基本使用

/**Array.prototype.reduce(callback,initial) 方法 [通常用于累加]
    + callback(preValue,nowItem,source) 回调函数
        + preValue 该参数为上一个 callback 回调的返回值 
        + 
    + initial 该参数定义第一次执行 callback 的 preValue
 */

    let items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    let resolve = items.reduce((preValue,nowItem) => {
        return preValue + nowItem // 每次执行该回调让上一次的值加上当前值 [实现累加]
    },0) // reduce 第二个参数 initial 也可以不传
    console.log(resolve) // 55

Array.isArray [静态方法]

用于确定传递的值是否是一个 Array

基本使用

    Array.isArray([1, 2, 3]);  // true
    Array.isArray({foo: 123}); // false
    Array.isArray('foobar');   // false
    Array.isArray(undefined);  // false


    // 下面的函数调用都返回 true
    Array.isArray([]);
    Array.isArray([1]);
    Array.isArray(new Array());
    Array.isArray(new Array('a', 'b', 'c', 'd'))
    Array.isArray(new Array(3));
    // 鲜为人知的事实:其实 Array.prototype 也是一个数组。
    Array.isArray(Array.prototype);

    // 下面的函数调用都返回 false
    Array.isArray();
    Array.isArray({});
    Array.isArray(null);
    Array.isArray(undefined);
    Array.isArray(17);
    Array.isArray('Array');
    Array.isArray(true);
    Array.isArray(false);
    Array.isArray(new Uint8Array(32))
    Array.isArray({ __proto__: Array.prototype });

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**isArray
 *  判断传入的值是否为数组
 */
    Array.isArray_k = function (element){
        let state = Object.prototype.toString.call(element) === '[object Array]' ? true : false
        return state
    }

Array.of [静态方法]

通过可变数量的参数创建一个新的Array实例,而不考虑参数的数量或类型

基本使用

/**Array.of()和 Array() 构造函数之间的区别在于对单个参数的处理:
    Array.of(7) - 创建一个具有单个元素 的数组 7
    Array(7) - 创建一个 为 的空数组(这意味着一个由 7 个空槽组成的数组,而不是具有实际 undefined 值的槽) length-7
*/
    Array.of(7); // [7]
    Array(7); // array of 7 empty slots

    Array.of(1, 2, 3); // [1, 2, 3]
    Array(1, 2, 3);    // [1, 2, 3]


// 更多使用方法与基本使用场景(参考文档)

基本实现

/**of方法
    可变数量的参数创建一个新的**Array**实例
 */
    Array.of_k = function (){
        let newArr = []
        for(let i=0;i<arguments.length;i++){
            newArr.push(arguments[i])
        }
        return newArr
    }

数组基本常用方法(pop 、push 、shift 、 unshift 、reverse)

基本使用

// 1.pop - 删除最后一项的元素
    const arr_pop = [1,2,3]
    console.log(arr_pop.pop()) // 3
    console.log([].pop()) // undefined
    console.log(arr_pop) // [1,2]

// 2.push - 在最后添加元素
    const arr_push = [1]
    console.log(arr_push.push_k(2)) // 2
    console.log(arr_push.push_k(3,4)) // 4
    console.log(arr_push) // [1,2,3,4]

// 3.shift - 删除最前项的元素
    const arr_shift = [1,2,3]
    console.log(arr_shift.shift_k()) // 1
    console.log(arr_shift) // [2,3]

// 4.unshift - 在最前面添加元素
    const arr_unshift = [1]
    console.log(arr_unshift.unshift_k(2)) // 2
    console.log(arr_unshift.unshift_k(3,4)) // 4
    console.log(arr_unshift) // [3,4,2,2]

// 5.reverse - 反转数组顺序
    const arr_reverse = [1,2,3,[10,20]]
    console.log(arr_reverse.reverse()) // [ [ 10, 20 ], 3, 3, [ 10, 20 ] ]
    console.log(arr_reverse) // [ [ 10, 20 ], 3, 3, [ 10, 20 ] ]

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**1.pop - 从数组中删除最后一个元素,并返回该元素的值(此方法会更改数组的长度)
 *   从数组中删除的元素(当数组为空时返回undefined)
 */
    Array.prototype.pop_k = function (){
        let retRemove = this[this.length-1] || undefined
        this.length>=0 ? this.length = this.length-1 : undefined // 长度减1,删除最后一位
        return retRemove
    }

/**2.push - 将一个或多个元素添加到数组的末尾,并返回该数组的新长度
    语法:
        push(element0)
        push(element0, element1)
        push(element0, element1, … , elementN)
 */
    Array.prototype.push_k = function (){
        let len = this.length 
        for(let i=0;i<arguments.length;i++){
            this[len] = arguments[i]
            len++
        }
        return this.length
    }

 /**3.shift - 从数组中删除第一个元素,并返回该元素的值
  */
    Array.prototype.shift_k = function (){
        let retRemove = this[0] || undefined,
            len = 1
        for(let i=0;i<this.length;i++){ // 让整体元素都向前移一位,此时数组的最后一位为undefined(删除即可)
            this[i] = this[len]
            len++
        }
        this.length>=0 ? this.length = this.length-1 : undefined // 删除最后一位
        return retRemove
    }

/**4.unShift - 将一个或多个元素添加到数组的开头,并返回该数组的新长度
 */
    Array.prototype.unshift_k = function (addElement){
        function execute_unshift(arg){  // 封装一个函数,使其添加一个长度并整体向后移一位,并将对应的单个实参放置在第一位(从而使得数组可以向前添加一位)
            for(let i=arg.length-1;i>=0;i--){ // 遍历每一个实参,并且每一个实参都会添加至最前面,其余的整体向后移一为(会增加一个长度)
                this[this.length] = this[this.length-1]
                let len = this.length - 3
                for(let i=this.length-2;i>0;i--){
                    this[i] = this[len]
                    len--
                }
                this[0] = arg[i]
            }
        }
        let arg = Object.values(arguments) // 获取所有实参
        execute_unshift.call(this,arg)
        return this.length
    }

/**5.reverse(反向)- 将数组中元素的位置颠倒,并返回该数组 
 *  数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个(会改变原数组)
 */
    Array.prototype.reverse_k = function (){
        function executeReverse (target,origin){
            let len = 0
            for(let i=target.length-1;i>=0;i--){
                origin[len] = target[i]
                len++
            }
            return target
        }
        let arr = (executeReverse(this,[]))
        let arr2 = (executeReverse(arr,this))
        for(let i=0;i<arr2.length-1;i++){
            this[i] = arr2[i]
        }
        arr = null,arr2=null
        console.log(arr)
        return this  
    }

toString

方法返回一个字符串,表示指定的数组及其元素

基本使用

    const arr_toString = [1,2,3]
    console.log(arr_toString.toString()) // '1,2,3'

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**toString方法  -  方法返回一个字符串,表示指定的数组及其元素
 */
    Array.prototype.toString_k = function (){
        let strSpace = ''
        for(let i=0;i<this.length;i++){
            this.length-1 === i ? strSpace += this[i] : strSpace += this[i] + ','
        }
        return strSpace
    }

values

返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值 - 可迭代,即可使用next/next.value等

基本使用

    const arr = ['a', 'b', 'c', 'd', 'e'];
    // 生成一个可迭代数组
    const iterator = arr.values();
    iterator.next();               // Object { value: "a", done: false }
    iterator.next().value;         // "b"
    iterator.next()["value"];      // "c"
    iterator.next();               // Object { value: "d", done: false }
    iterator.next();               // Object { value: "e", done: false }
    iterator.next();               // Object { value: undefined, done: true }
    iterator.next().value;         // undefined

sort

方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的

由于它取决于具体实现,因此无法保证排序的时间和空间复杂性(即它是由asc码来比较的,所以是无法保证完全能跟人理解的来的)

基本使用

// 基本使用 - 字符串排序与数字排序  --  它的排序是根据 Unicode 位点进行排序 (asc码)
    const months = ['March', 'Jan', 'Feb', 'Dec'];
    months.sort();
    console.log(months);
    // Expected output: Array ["Dec", "Feb", "Jan", "March"]

    const array1 = [1, 30, 4, 21, 100000];
    array1.sort();
    console.log(array1);
    // Expected output: Array [1, 100000, 21, 30, 4]

/**sort方法
 *  参数(回调函数):
        compareFn - 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的 Unicode 位点进行排序(回调函数)
            compareFn参数:
                1.first - 第一个用于比较的元素
                2.two - 第二个用于比较的元素
*   返回值:
        排序后的数组  --  注意,数组已原地排序,并且不进行复制
 */
    // 函数比较格式的基本使用:(跟多看文档与自身理解)
        function compareFn(a, b) {
            if (在某些排序规则中,a 小于 b) {
                return -1;
            }
            if (在这一排序规则下,a 大于 b) {
                return 1;
            }
            // a 一定等于 b
            return 0;
        }

// 更多使用方法与基本使用场景(参考文档)

some

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

基本使用

    // 基本使用
        const arr = [1,2,3,4]
        function test(el){
            console.log(el)
            return el > 2
            
        }
        console.log(arr.some_k(test))

    // 判断数组中是否存在某个值 (方法封装实现)
        var fruits = ['apple', 'banana', 'mango', 'guava'];
        function checkAvailability(arr, val) {
            return arr.some(function(arrVal) {
                return val === arrVal;
            });
        }
        checkAvailability(fruits, 'kela');   // false
        checkAvailability(fruits, 'banana'); // true

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**some - 测试数组中是不是至少有 1 个元素通过了被提供的函数测试
    - 当测试的数组中没有一个通过测试的,返回false - 由一个或多个的返回true
    - 参数:callback(回调函数),thisArg(this指向)
        - callback:所提供的测试函数,其中有3个参数分别为(element、index、array)
        - thisArg:指定callback函数的this指向
            默认会是相当于严格模式下独立调用函数,即 undefined
 */
    Array.prototype.some_k = function (callback,thisArg){
        thisArg = thisArg || undefined
        for(let i=0;i<this.length;i++){
            let judge= callback(this[i],i,this)
            if(judge){
                return true
            }
        }   
        return false
    }

slice

返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变

相当于是可以指定索引位置来进行浅克隆

基本使用

    const arr = [1,2,3,4]
    const cloneArr = arr.slice(1,3) // [2,3] - 从索引1到3不包括3,即 [1,3)
    console.log(cloneArr) // [2,3]

// 更多使用方法与基本使用场景(参考文档)

方法实现

/**slice(薄/片) - 指定索引进行浅克隆
 *  参数:
        begin - 开始索引 【可选 - 默认从 0 开始】
        end - 结束索引(不包括本身,即相当于是前闭后开) 【可选 - 默认到最后】
 */
    Array.prototype.slice_k = function (begin,end){
        begin = begin || 0
        end = end || this.length
        let newArr = []
        for(let i=begin;i<end;i++){
            newArr.push(this[i])
        }
        return newArr
    }

splice - 拼接

方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容 – 会改变原数组

基本使用

/**splice - 拼接
 *  - 删除、替换、添加

    - 该方法有 3  个参数:
        start - 指定修改的开始位置(默认 0)
            1.当为负数并且绝对值不大于数组长度时,表示从倒数第几为开始
            2.当为负数并且绝对值大于数组长度时,使用默认 0 
            3.如果超出了数组的长度,则从数组末尾开始添加内容(正数)
        delteCount - 删除元素的个数(正数)【可选】
            1.如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)
            2.如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素
            3.果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除
        item1, item2, .. - 要添加进数组的元素,从start 位置开始 - 如果不指定,则 splice() 将只删除数组元素 【可选】

    - 返回值:
        由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组 
 */
    const arr = ['kong','xiang','huang','dneg']
    console.log(arr.splice(1,6)) // 1.deleteCount大于star后面元素的总数,会将start后面的元素都移除(包括start本身)  --  [ 'xiang', 'huang', 'dneg' ]
    console.log(arr.splice(0,0)) // 2.deleteCount为0或负数时,不进行移除 
    console.log(arr.splice(0)) // 3.deleteCount省略 - star后面的元素都将被移除
    console.log('arr',arr)
  • 22
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值