7<保姆教程>》JavaScript基础(内置对象+方法属性的介绍与使用+方法实现)*持续更新中

230 阅读8分钟

内置对象

概述

// 介绍
js中的对象分为3种:自定义对象,内置对象,浏览器对象
前面两种对象是js基础的内容,属于ECMAScript;第三个浏览器对象属于我们js独有的(到JS API会讲解)
内置对象就是值JS语言自带的一些对象,这些对象共开发者使用,并提高了一些常用的或最基本而必要的功能(属性和方法)
内置对象最大的优点就是帮助我们快速开发
js提供了多个内置对象:Math,Date,Array,String// 怎么学(个人观点)
要弄懂:
该方法具体是实现什么功能的
参数是什么,有几个
有没有返回值,返回值是什么
会不会改变原来的值
// 计划
内置对象的方法有点多,不过本章节后续会有一些比较常用的内置对象的方法的介绍和自己封装一个跟其一样的方法

Array

isArray

    // 判断值是否数组
    // 语法:Array.isArray(obj)
    // 参数:obj要检测的值
    // 返回值:布尔类型
    // 不会改变原值
    var arr = [2, 31, 123, 1]
    console.log(Array.isArray(arr)) //true

    // 自己实现一个
    Array.isArray_h = function(obj) {
        return obj instanceof Array
    }
    console.log(Array.isArray_h(arr))

indexOf/lastIndexOf

    - 以 indexOf为例,lastIndexOf的查找顺序相反,参数用法一样
    // 返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1
    // 语法:arr.indexOf(searchElement[, fromIndex])
    // 参数:
    /*  
    searchElement:要查找的元素
    fromIndex(可选):开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。
        如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,
        -2表示从倒数第二个元素开始查找 ,以此类推。 
        注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。
        如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.
     */
    // 返回值:首个被找到的元素在数组中的索引位置; 若没有找到则返回 -1
    // 不会改变原值
   var arr = [2, 313, 112, 31, 231, 1, 3, 33, 3, 3, 0]
    console.log(arr.indexOf(3)) //6
    console.log(arr.indexOf(3, 10)) //-1
    console.log(arr.indexOf(3, 11)) //-1
    console.log(arr.indexOf(3, 8)) //8
    console.log(arr.indexOf(3, -1)) //-1
    console.log(arr.indexOf(3, -3)) //8
    console.log(arr.indexOf(3, -100)) //6
        // 自己实现一个
    Array.prototype.indexOf_h = function(searchElement, fromIndex = 0) {
        // 核心思路:通过fromIndex来判断从哪个位置开始遍历数组
        fromIndex = (fromIndex < 0 ? this.length + fromIndex : fromIndex) < 0 ? 0 : (fromIndex < 0 ? this.length + fromIndex : fromIndex)
        for (var i = fromIndex; i < this.length; i++) {
            if (this[i] === searchElement) {
                return i
            }
        }
        return -1
    }
    console.log('------------------------------------')
    console.log(arr.indexOf_h(3)) //6
    console.log(arr.indexOf_h(3, 10)) //-1
    console.log(arr.indexOf_h(3, 11)) //-1
    console.log(arr.indexOf_h(3, 8)) //8
    console.log(arr.indexOf_h(3, -1)) //-1
    console.log(arr.indexOf_h(3, -3)) //8
    console.log(arr.indexOf_h(3, -100)) //6

pop/shift

    // 从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
    // 语法:arr.pop()
    // 参数:无
    // 返回值:从数组中删除的元素(当数组为空时返回undefined)。
    // 会改变原值
    var arr = [2, 31, 11, 23, 1]
    var arr2 = [2, 31, 11, 23, 1]
    var arr1 = []
    console.log(arr.pop(arr)) //1
    console.log(arr) // [2, 31, 11, 23]
    console.log(arr1.pop()) //undefined
    console.log(arr1) //[]

    // 自己实现一个
    Array.prototype.pop_h = function() {
        if (this.length) {
            var el = this[this.length - 1]
            this.length = this.length - 1
            return el
        } else {
            return undefined

        }
    }
    console.log('-----------------------------')
    console.log(arr2.pop_h()) //1
    console.log(arr2) // [2, 31, 11, 23]
    console.log(arr1.pop_h()) //undefined
    console.log(arr1) //[]
     
    // shift----------------------

    // 从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
    // 语法:arr.shift()
    // 参数:无
    // 返回值:从数组中删除的元素(当数组为空时返回undefined)。
    // 会改变原值
    var arr = [1, 231, 1231, 1111]
    var arr1 = [1, 231, 1231, 1111]
    console.log(arr.shift())
    console.log(arr)
    Array.prototype.shift_h = function() {
        if (this.length) {
            var el = this[0]
            for (var i = 1; i < this.length; i++) {
                this[i - 1] = this[i]
            }
            this.length = this.length - 1
                // 注意:this=值,这样是不行的会报错
            return el
        } else {
            return undefined
        }
    }
    console.log('------------------------')
    console.log(arr1.shift_h()) //1
    console.log(arr1) //[231, 1231, 1111]

push/unshift

    // 以unshift(push相反)为例:将一个或多个元素添加到数组的开头
    // 语法:arr.unshift(element1, ..., elementN)
    // 参数:要添加到数组开头的元素或多个元素。
    // 返回值:返回改变后数组的长度
    // 改变原值
    var arr = [1, 231, 1231, 1111]
    var arr1 = [1, 231, 1231, 1111]
    console.log(arr.unshift('a', 'b')) //6
    console.log(arr) //['a', 'b', 1, 231, 1231, 1111]
    // 自己实现一个
    Array.prototype.unshift_h = function() {
        var arr = [...arguments, ...this]
        for (var i = 0; i < arr.length; i++) {
            this[i] = arr[i]
        }
        return this.length
    }
    console.log('-----------------------')
    console.log(arr1.unshift_h('a', 'b')) //6
    console.log(arr1) //['a', 'b', 1, 231, 1231, 1111]

concat

    // 合并两个或多个数组(值)。此方法不会更改现有数组,而是返回一个新数组。
    // 语法:arr.concat(value1[, value2[, ...[, valueN]]])
    // 参数:数组和/或值,将被合并到一个新的数组中。如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝。
    // 返回值:新的 Array 实例
    // 不改变原值
    let arr = [1, 2, 3]
    let arr1 = arr.concat()
    let arr2 = arr.concat(1)
    let arr3 = arr.concat(1, [1, 2, 3])
    let arr4 = arr.concat(1, [1, 2, 3, [5, 2]])
    console.log(arr1) //[1,2,3]
    console.log(arr2) //[1,2,3,1]
    console.log(arr3) //[1, 2, 3, 1, 1, 2, 3]
    console.log(arr4); // [1, 2, 3, 1, 1, 2, 3, [5,2]]
    console.log(arr) //[1,2,3]
    console.log('----------------------------------------------')
        // 自己实现一个
    Array.prototype.concat_h = function() {
        let newArr = [...this]
        let qur = [...arguments]
        qur.forEach(v => {
            if (Array.isArray(v)) {
                for (let i = 0; i < v.length; i++) {
                    newArr.push(v[i])
                }
            } else {
                newArr.push(v)
            }
        })
        return newArr
    }
    let arr5 = arr.concat()
    let arr6 = arr.concat(1)
    let arr7 = arr.concat(1, [1, 2, 3])
    let arr8 = arr.concat(1, [1, 2, 3, [5, 2]])
    console.log(arr5) //[1,2,3]
    console.log(arr6) //[1,2,3,1]
    console.log(arr7) //[1, 2, 3, 1, 1, 2, 3]
    console.log(arr8); // [1, 2, 3, 1, 1, 2, 3, [5,2]]
    console.log(arr) //[1,2,3]

every/some

    - 以every为例子,some相反,some只有有一个元素满足条件则可,空数组返回false
    // 测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
    // 语法:arr.every(callback(element[, index[, array]])[, thisArg])
    // 参数:
    /*   
        callback
        用来测试每个元素的函数,它可以接收三个参数:
            element
            用于测试的当前值。
            index可选
            用于测试的当前值的索引。
            array可选
            调用 every 的当前数组。
        thisArg
        执行 callback 时使用的 this 值,如果callback是箭头函数则无效。 
    */
    // 返回值:如果回调函数的每一次返回都为 truthy 值,返回 true ,否则返回 false,如果是空数组则返回true。
    // 不改变原值

    let arr = [10, 20, 10]
    let arr1 = []
    console.log(arr.every(v => v > 1)) //true
    console.log(arr.every(v => v > 10)) //false
    console.log(arr1.every(v => v > 10)) //true
    console.log(arr) //[10, 20, 10]
    console.log('-------------------------');
    // 自己实现
    Array.prototype.every_h = function(fn, thisArg) {
        thisArg = thisArg ? thisArg : this //如果传了就指向传的如果不传就是arr
        let r = true
        for (var i = 0; i < this.length; i++) {
            r = fn.call(thisArg, this[i], i, this)
            if (!r) return r

        }
        return r
    }
    console.log(arr.every_h(v => v > 1)) //true
    console.log(arr.every_h(v => v > 10)) //false
    console.log(arr1.every_h(v => v > 10)) //true
    console.log(arr) //[10, 20, 10]

filter

    // 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
    // 语法:arr.filter(callback(element[, index[, array]])[, thisArg])
    // 参数:
    /*   
      callback
        用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。它接受以下三个参数:
        element
        数组中当前正在处理的元素。
        index可选
        正在处理的元素在数组中的索引。
        array可选
        调用了 filter 的数组本身。
    thisArg可选
    执行 callback 时,用于 this 的值,当callback是箭头函数时无效。
    */
    // 返回值:一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。
    // 不改变原值
    let arr = [{
        name: '李华',
        sex: 1
    }, {
        name: '李华1',
        sex: 1
    }, {
        name: '李华2',
        sex: 2
    }, {
        name: '李华3',
        sex: 1
    }, ]
    let arr1 = []
    let newArr = arr.filter(v => v.sex == 1)
    let newArr1 = arr1.filter(v => v.sex == 1)
    let newArr2 = arr.filter(v => v.sex == 3)
    console.log(newArr)
    console.log(newArr1)
    console.log(newArr2)
    console.log(arr)
    console.log(arr1)
    console.log('---------------------------------');
    // 自己实现
    Array.prototype.filter_h = function(fn, thisArg) {
        thisArg = thisArg ? thisArg : this //如果传了就指向传的如果不传就是arr
        let r = true
        const newArr = []
        for (var i = 0; i < this.length; i++) {
            r = fn.call(thisArg, this[i], i, this)
            if (r) {
                newArr.push(this[i])
            }

        }
        return newArr
    }
    let newArr3 = arr.filter_h(v => v.sex == 1)
    let newArr4 = arr1.filter_h(v => v.sex == 1)
    let newArr5 = arr.filter_h(v => v.sex == 3)
    console.log(newArr3)
    console.log(newArr4)
    console.log(newArr5)
    console.log(arr)
    console.log(arr1)

find/findIndex

    // find返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
    // 语法:arr.find(callback[, thisArg])
    // 参数:
    /*   
      callback
        在数组每一项上执行的函数,接收 3 个参数:
        element
        当前遍历到的元素。
        index可选
        当前遍历到的索引。
        array可选
        数组本身。
    thisArg可选
        执行回调时用作this 的对象,callback为箭头函数时无效。 
    */
    // 返回值:数组中第一个满足所提供测试函数的元素的值,否则返回 undefined。
    // 不改变原值
    let arr = [2, 1313, 11, 3, 2]
    let arr1 = [{
        name: '李华',
        id: 2
    }, {
        name: '李华',
        id: 3
    }, {
        name: '李华1',
        id: 4
    }, ]
    let arr2 = []
    console.log(arr.find(v => v == 3)) //3
    console.log(arr1.find(v => v.name == '李华')) //{name: '李华', id: 2}
    console.log(arr2.find(v => v.name == '李华')) //undefined
    console.log('-----------------------------------------')
    Array.prototype.find_h = function(fn, thisArg) {
        thisArg = thisArg ? thisArg : this
        for (let i = 0; i < this.length; i++) {
            if (fn.call(thisArg, this[i], i, this)) {
                return this[i]
            }
        }
    }
    console.log(arr.find_h(v => v == 3)) //3
    console.log(arr1.find_h(v => v.name == '李华')) //{name: '李华', id: 2}
    console.log(arr2.find_h(v => v.name == '李华')) //undefined
    // findIndex
    // 和find非常相似,只不过他返回的是索引,找不到返回-1而不是undefined

forEach

    // 对数组的每个元素执行一次给定的函数。
    // 语法:arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
    // 参数:
    /*   
    callback
        为数组中每个元素执行的函数,该函数接收一至三个参数:
        currentValue
        数组中正在处理的当前元素。
        index 可选
        数组中正在处理的当前元素的索引。
        array 可选
        forEach() 方法正在操作的数组。
    thisArg 可选
        可选参数。当执行回调函数 callback(箭头函数时无效) 时,用作 this 的值。 
    */
    // 返回值:undefined。
    // 不改变原值
    let arr = [1, 2, 3, 4]
    let arr1 = [{
        id: 1
    }, {
        id: 2
    }, {
        id: 3
    }, ]
    let sun = 0
    arr.forEach(v => {
        sun += v
    })
    arr1.forEach(v => {
        v.key = v.id
    })
    console.log(sun) //10
    console.log(arr1) //[{id: 1, key: 1},{id: 2, key: 2},{id: 3, key: 3}]
    Array.prototype.forEach_h = function(fn, thisArg) {
        thisArg = thisArg ? thisArg : this
        for (var i = 0; i < this.length; i++) {
            fn.call(thisArg, this[i], i, this)
        }
    }
    let sun1 = 0
    arr.forEach_h(v => {
        sun1 += v
    })
    arr1.forEach_h(function(v, i, arr) {
        console.log(v)
        console.log(i)
        console.log(arr)
        console.log(this)
    })
    console.log(sun) //10

includes

    // 和indexOf很相似,只不过includes返回的是布尔值而不是索引
    // 用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
    // 语法arr.includes(valueToFind[, fromIndex])
    // 参数:
    /*   
    valueToFind
        需要查找的元素值。
    fromIndex 可选
        从fromIndex 索引处开始查找 valueToFind。如果为负值,
        则按升序从 array.length + fromIndex 的索引开始搜 (即使从末尾开始往前跳 fromIndex 的绝对值个索引,然后往后搜寻)。默认为 0。    
    */
    // 返回值:返回一个布尔值 Boolean 。
    // 不改变原值

join

    // 将一个数组的所有元素连接成一个字符串并返回这个字符串
    // 语法arr.join([separator])
    // 参数:
    /*   
   separator 可选
        指定一个字符串来分隔数组的每个元素。如果需要,将分隔符转换为字符串。如果缺省该值,数组元素用逗号(,)分隔。
        如果separator是空字符串(""),则所有元素之间都没有任何字符。
    */
    // 返回值:一个所有数组元素连接的字符串。如果 arr.length 为0,则返回空字符串 。
    // 不改变原值
    let arr = [1, 2, 3]
    let arr1 = []
    console.log(arr.join()) //1,2,3
    console.log(arr.join('')) //123
    console.log(arr.join('-')) //1-2-3
    console.log(arr1.join('-')) //空字符串
    console.log('-------------------------');
    // 自己实现
    Array.prototype.forEach_h = function(fn, thisArg) { //用一下封装的forEach_h,因为下面要用到遍历
        thisArg = thisArg ? thisArg : this
        for (var i = 0; i < this.length; i++) {
            fn.call(thisArg, this[i], i, this)
        }
    };
    // 正片
    Array.prototype.join_h = function(separator) {
        let str = ''
        separator = separator != undefined ? separator : ','
        this.forEach_h(v => {
            str = str + v + separator
        })
        str = separator ? str.substring(0, str.length - 1) : str
        return str
    }
    console.log(arr.join_h()) //1,2,3
    console.log(arr.join_h('')) //123
    console.log(arr.join_h('-')) //1-2-3
    console.log(arr1.join_h('-')) //空字符串

slice

    // 截取数组
    // 语法arr.slice([begin[, end]])
    // 参数:
    /*   
    begin 可选
        提取起始处的索引(从 开始),从该索引开始提取原数组元素。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,
        (如果该负数和数组的长度相加后依然为负数则从0开始)
        如果 被省略,则会从0开始。如果超出原数组的索引范围,则会返回空数组。
    end 可选
        提取终止处的索引(不会取到该索引处);如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取,
        (如果该负数和数组的长度相加后依然为负数则也返回空数组) 
        如果 被省略,则 会一直提取到原数组末尾。如果 大于数组的长度, 也会一直提取到原数组末尾
    */
    // 返回值:一个含有被提取元素的新数组。
    // 不改变原值
    let arr = [1, 2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice()) // [1, 2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice(1)) // [2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice(-1)) // [8]
    console.log(arr.slice(-10)); // [1, 2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice(4, 2)); // []
    console.log(arr.slice(4, -2)); // [5, 6]
    console.log(arr.slice(4, -5)); // []
    console.log('----------------------------------------')
        // 自己实现
    Array.prototype.slice_h = function(begin, end) {
        begin = begin ? begin : 0
        begin = begin < 0 ? this.length + begin : begin
        begin = begin < 0 ? 0 : begin
        end = end ? end : this.length
        end = end < 0 ? this.length + end : end
        let newArr = []
        for (var i = begin; i < end; i++) {
            newArr.push(this[i])
        }
        return newArr
    }
    console.log(arr.slice_h()) // [1, 2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice_h(1)) // [2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice_h(-1)) // [8]
    console.log(arr.slice_h(-10)); // [1, 2, 3, 4, 5, 6, 7, 8]
    console.log(arr.slice_h(4, 2)); // []
    console.log(arr.slice_h(4, -2)); // [5, 6]
    console.log(arr.slice_h(4, -5)); // []

splice

   // 删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组
    // 语法 array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
    // 参数:
    /*    
    start​
        指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;
        如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);
        如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
    deleteCount 可选
        整数,表示要移除的数组元素的个数。如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。
        如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),
        那么start之后数组的所有元素都会被删除。如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
    item1, item2, ... 可选
        要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。
    */
    // 返回值:由被删除的元素组成的一个数组。如果没有删除元素,则返回空数组。
    // 改变原值
    let arr = [23, 123, 1, 31, 21, 23, 0]
    console.log(arr.splice(1, -2, 'a'), '被删除的')
    console.log(arr, '改变后的')
    console.log('------------------------------')
    let arr1 = [23, 123, 1, 31, 21, 23, 0]
    Array.prototype.splice_h = function() {
        let pr = [...arguments]
        let start = pr[0] //删除的开始位置
        start = start < 0 ? this.length + start : start
        start = start > 0 ? start : 0
        if (start == undefined) return []
        let deleteCount = pr[1] //删除的个数
        deleteCount = deleteCount != undefined ? deleteCount : this.length
        deleteCount = deleteCount > 0 ? deleteCount : 0
        let itemArr = pr.slice(2) //添加的元素
        let deleteCountArr = [] //删除的数组
        let newArr = [] //新数组
        newArr = [...this.slice(0, start)]
        if (deleteCount >= 0) {

            deleteCountArr = this.slice(start, start + deleteCount)
        }
        newArr = [...newArr, ...itemArr, ...this.slice(start + deleteCount)]
        deleteCountArr.forEach((v, i) => {
            this[i] = v
        })
        this.length = 0
        newArr.forEach((v, i) => {
            this[i] = v
        })
        return deleteCountArr
    }
    console.log(arr1.splice_h(1, 2, 'a'), '被删除的')
    console.log(arr1, '改变后的')

reverse

    // 将数组中元素的位置颠倒
    // 语法 arr.reverse()
    // 参数:无
    // 返回值:颠倒后的数组。
    // 改变原值
    let arr = [1, 2, 3, 4]
    console.log(arr.reverse()) //[4, 3, 2, 1]
    console.log(arr) //[4, 3, 2, 1]
    console.log('--------------------------------------')
    Array.prototype.reverse_h = function() {
        for (var i = 0; i < this.length / 2; i++) {
            var tp = this[i]
            this[i] = this[this.length - 1 - i]
            this[this.length - 1 - i] = tp
        }
        return this
    }
    console.log(arr.reverse()) //[1, 2, 3, 4]
    console.log(arr) //[1, 2, 3, 4]

sort

    /*  改造了改造了,原生的那个确定有很多其他用法,但是用的不多,好像就没用过其他的,所以就改成这样了,参数为必填的了,
        原生那个为可选,有兴趣可以去看看,没兴趣可以直接用我这个 !!!!!!!!!
    */
    // 排序
    // 语法 arr.sort(compareFunction)
    // 参数:
    /*    
        compareFunction 
            用来指定按某种顺序进行排列的函数
            firstEl
                第一个用于比较的元素。
            secondEl
                第二个用于比较的元素。 
    */
    // 返回值:排序后的数组。
    // 改变原值
    let arr = [23, 123, 1, 31, 21, 23, 0]
    let arr1 = [{
        age: 10
    }, {
        age: 2
    }, {
        age: 1
    }, {
        age: 30
    }];

    // console.log(arr)
    // console.log(arr.sort((a, b) => a - b))

    // 自己实现(有小区别,原来的可以不用传参数,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
    // 还有一些其他用法,但是我在实际开发中好像没有用过,感觉不到他们的用处,是我菜了)
    Array.prototype.sort_h = function(fn) {
        for (var i = 0; i < this.length - 1; i++) {
            for (var k = 0; k < this.length - 1 - i; k++) {
                var f = fn(this[k], this[k + 1])
                if (f > 0) {
                    var tp = this[k]
                    this[k] = this[k + 1]
                    this[k + 1] = tp
                }
            }
        }
        return this
    }
    console.log(arr.sort_h((a, b) => a - b)) // [0, 1, 21, 23, 23, 31, 123]
    console.log(arr1.sort_h((a, b) => b.age - a.age)) //[{age: 30},{age: 10},{age: 2},{age: 1}]

flat

    //按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回 (es6的方法)
    // 语法 arr.flat([depth])
    // 参数: 指定要提取嵌套数组的结构深度,默认值为 1。
    // 返回值:新数组。
    // 不改变原值
    let arr = [1, 2, 3, [4, 5, [6, 7, [8, 9]]]]
    console.log(arr.flat(1))
    console.log(arr.flat(2))
    console.log(arr.flat(Infinity))
    console.log('-----------------------------------------')
        // 自己实现
    Array.prototype.flat_h = function(num = 1) {
        const res = [];
        let _this = this;
        (function fn(_this, num) {
            _this.forEach((item) => {
                if (Array.isArray(item) && num > 0) {
                    res.concat(fn(item, num - 1))
                } else {
                    res.concat(item)
                }
            })
        })(_this, num)

        return res;
    }
    console.log(arr.flat_h(1))
    console.log(arr.flat_h(2))
    console.log(arr.flat_h(Infinity))