模拟实现数组新增的东西

2,009 阅读2分钟

前言

ES6新增了很多属性、方法以及某些特性,本系列主要通过模拟实现的方式来重学ES6,以便帮助自己更深入的的理解那些新增的东西。

本文目标: 通过模拟实现,深入理解ES6数组身上新增的东西

说明: 文中对一下方法简单介绍,然后完成模拟实现

22222.jpg

模拟实现数组新增的东西

静态方法

Array.from()

介绍

参数: 第一个参数接收一个类数组或其他部署了Iterator接口的数据结构,第二个可选参数接受一个函数,作用类似map

作用: 把接收的第一个参数转成真数组,并可通过第2个参数进行整理

返回值: 返回新的数组,不改变原对象

模拟实现:Array._from()

Array._from = (likeArray, callback) => {
    let res = [].slice.call(likeArray)
    return (typeof callback == 'function') ? res.callback() : res            
}
console.log(Array._from('asd'))// ["a", "s", "d"]
console.log(Array.from('asd'))// ["a", "s", "d"]
let divs = document.querySelectorAll('div')
console.log(Array._from(divs))//[div, div, div]
console.log(Array.from(divs))//[div, div, div]

Array.of()

介绍

参数: 可接收n个参数

作用: 将一组参数转成数组

返回值: 返回该数组

模拟实现:Array._of()

Array._of = (...args) => args;
console.log(Array._of(1, 2, 3))//[1,2,3]
console.log(Array.of(1, 2, 3))//[1,2,3]

实例方法

copyWithin()

介绍

参数: 可接收三个参数,且参数一般为数值,如果不是数值会转成数值,如果出现负数,表示倒数第几位。第一个参数表示从该位置开始替换数据,第二个参数表示从该位置开始读取数据(默认为0),第三个表示读取数据到该位置(默认为数组长度)

作用: 将数组中某位置到某位置的数据复制,然后到从指定位置开始替换对应长度的数据

返回值: 返回当前数组,即会改变原数组

模拟实现:_copyWithin()

Array.prototype._copyWithin = function (target, start = 0, end = this.length) {
    // 1. 将负值情况处理了
    if (target < 0) {
        target += this.length
    }
    if (start < 0) {
        start += this.length
    }
    if (end < 0) {
        end += this.length
    }
    // 2.找到要拷贝的值,并在指定位置逐一替换
    for (let index = start; index < end; index++) {
        // this[index];//需要拷贝的值
        if (target < this.length) {
            console.log(this[target],this[index])
            this[target] = this[index];
            target++
        }
    }
    return this
}
console.log([1, 2, 3, 4].copyWithin(2))//[1, 2, 1, 2]
console.log([1, 2, 3, 4]._copyWithin(2))//[1, 2, 1, 2]

find()

介绍

参数: 第一个参数是一个callback回调函数,第二个参数是this指向

作用: 遍历数组成员并执行回调,返回第一个符合条件的数组成员

返回值: 返回第一个执行回调后返回值为true的成员没有找到返回undefined

模拟实现:_find()

Array.prototype._find = function (callback, self) {
    if (typeof callback === 'function') {
        if (this.length) {
            for (let i = 0; i < this.length; i++) {
                // 找出每一个成员传入回调中,执行如果为真,则返回该值
                if (callback.call(self, this[i], i, this)) {
                    return this[i]
                }
            }
        }
    }
}
let a = [1, 2, 3]    
console.log(a._find(function (val, index, arr) { return val == 1 }));//1
console.log(a.find(function (val, index, arr) { return val == 1 }));//1

findIndex()

介绍

参数: 第一个参数是一个callback回调函数,第二个参数是this指向

作用: 跟find方法类似,只不过是查找第一个符合条件的数组成员的index值

返回值: 返回第一个符合条件的成员的index

模拟实现:_findIndex()

Array.prototype._findIndex = function (callback, self) {
    if (typeof callback === 'function') {
        if (this.length) {
            for (let i = 0; i < this.length; i++) {
                // 找出每一个成员传入回调中,执行如果为真,则返回该值
                if (callback.call(self, this[i], i, this)) {
                    return i
                }
            }
        }
    }
}
let a = [1, 2, 3]    
console.log(a._findIndex(function (val, index, arr) { return val == 1 }));//0
console.log(a.findIndex(function (val, index, arr) { return val == 1 }));//0

fill()

介绍

参数: 可接收三个参数,分别表示要填充的东西、填充的起始位置、填充的结束位置;后两个选填,默认值分别为0和数组长度

作用: 用于填充数组,将要填充的东西填充到指定的位置

返回值: 返回填充修改后的数组,即会改变原数组

模拟实现:_fill()

Array.prototype._fill = function (data, start = 0, end = this.length) {
    // 处理负值
    if (start < 0) {
        start += this.length
    }
    if (end < 0) {
        end += this.length
    }
    // 填充
    for (let i = start; i < end; i++) {
        this[i] = data;
    }
    return this
}
console.log(new Array(5)._fill('a', -2))//[empty × 3, "a", "a"]
console.log(new Array(5).fill('a', -2))//[empty × 3, "a", "a"]

entries(),keys() , values()

介绍

三者差不多,就放一起按说了

参数:

作用: keys()是对键名的遍历,values()是对键值的遍历,entries()是对键值对的遍历

返回值: 都返回一个遍历器对象

模拟实现:_keys()

Array.prototype._keys = function (){ 
    let temp = []   
    for (let i = 0; i < this.length; i++) {
        temp.push(i)       
    }
    return temp[Symbol.iterator]()
}
let arr = ['a','b','c']
console.log(arr._keys(),arr.keys());
for (const iterator of arr._keys()) {
    console.log(iterator);
}
for (const iterator of arr.keys()) {
    console.log(iterator);
}

结果如下:

image.png

模拟实现:_values()

Array.prototype._values = function (){ 
    let temp = []   
    for (let i = 0; i < this.length; i++) {
        temp.push(this[i])       
    }
    return temp[Symbol.iterator]()
}
let arr = ['a','b','c']
for (const i of arr._values()) {
    console.log(i);
}
for (const i of arr.values()) {
    console.log(i);
}

模拟实现:_entries()

Array.prototype._entries = function (){ 
    let temp = []   
    for (let i = 0; i < this.length; i++) {
        temp.push([i,this[i]])       
    }
    return temp[Symbol.iterator]()
}

includes()

介绍

参数: 接收一个需要判断的值

作用: 用于判断给定值是否包含在数组中

返回值: 返回true或false

模拟实现:_includes()

Array.prototype._includes = function (x) {
    for (let i = 0; i < this.length; i++) {
        if (Number.isNaN(x) && Number.isNaN(this[i])) {
            return true
        }
        if (x === this[i]) {
            return true
        }        
    }
    return false
}
let arr = [1,2,3,4,NaN]
console.log(arr._includes(2))//true
console.log(arr._includes(NaN))//true
console.log(arr._includes(5))//false

flat()

介绍

参数: 接收一个整数

作用: 用于将数组拉平或者叫拍平,拍平的深度取决于传递的参数,默认为2,表示拍平二维数组

返回值: 返回拍平后的数组,不改变原始数组

模拟实现:_flat()

Array.prototype._flat = function (n = 1) {
    return this.reduce((acc, val) => {
        return acc.concat(Array.isArray(val) && n > 0 ?
            val.flat(--n) : Array.isArray(val) ? [val] : val);
    }, [])
}
let arr = [1, [2, 3], ['a', 'b', ['c', 'd']]]
console.log(arr._flat(3))//[1, 2, 3, "a", "b", "c", "d"]

END

以上就是数组身上新增的一些东西的模拟实现!

真正的实现可能跟我写的不一样,不过没有关系,我们只要熟知这些方法具体干了什么,也就达到了这次学习的目的了!

如有疑问或建议,希望可以留言告知,感谢你!!