• 手写js原生方法总结(简版)


    Array篇

    定义一个测试数组

    const players = [
        { name: '科比', num: 24 },
        { name: '詹姆斯', num: 23 },
        { name: '保罗', num: 3 },
        { name: '威少', num: 0 },
        { name: '杜兰特', num: 35 }
    ]

    1、forEach

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_forEach = function (callback) {
        for (let i = 0; i < this.length; i++) {
            callback(this[i], i, this)
        }
    }
    
    players.sx_forEach((item, index, arr) => {
        console.log(item, index)
    })
    // { name: '科比', num: 24 } 0
    // { name: '詹姆斯', num: 23 } 1
    // { name: '保罗', num: 3 } 2
    // { name: '威少', num: 0 } 3
    // { name: '杜兰特', num: 35 } 4
    

     

    2、map

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_map = function (callback) {
        const res = []
        for (let i = 0; i < this.length; i++) {
            res.push(callback(this[i], i, this))
        }
        return res
    }
    
    console.log(players.sx_map((item, index) => `${item.name}--${item.num}--${index}`))
    // [ '科比--24--0', '詹姆斯--23--1', '保罗--3--2', '威少--0--3', '杜兰特--35--4' ]
    

      

    3、filter

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_filter = function (callback) {
        const res = []
        for (let i = 0; i < this.length; i++) {
            callback(this[i], i, this) && res.push(this[i])
        }
        return res
    }
    
    console.log(players.sx_filter(item => item.num >= 23))
    // [
    //     { name: '科比', num: 24 },
    //     { name: '詹姆斯', num: 23 },
    //     { name: '杜兰特', num: 35 }
    // ]

    4、every

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_every = function (callback) {
        let flag = true
        for (let i = 0; i < this.length; i++) {
            flag = callback(this[i], i, this)
            if (!flag) break
        }
    
        return flag
    }
    
    console.log(players.sx_every(item => item.num >= 23)) // false
    console.log(players.sx_every(item => item.num >= 0)) // true

    5、some

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_some = function (callback) {
        let flag = false
        for (let i = 0; i < this.length; i++) {
            flag = callback(this[i], i, this)
            if (flag) break
        }
    
        return flag
    }
    
    console.log(players.sx_some(item => item.num >= 23)) // true
    console.log(players.sx_some(item => item.num >= 50)) // false
    

      

     

    6、reduce

    参数代表含义

    • pre:前一项
    • next:下一项
    • index:当前索引
    • arr:数组本身
    Array.prototype.sx_reduce = function (callback, initValue) {
        let pre = initValue
        for (let i = 0; i < this.length; i++) {
            pre = callback(pre, this[i], i, this)
        }
        return pre
    }
    
    // 计算所有num相加
    const sum = players.sx_reduce((pre, next) => {
        return pre + next.num
    }, 0)
    console.log(sum) // 85
    

     

    7、findIndex

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_findIndex = function (callback) {
        for (let i = 0; i < this.length; i++) {
            if (callback(this[i], i, this)) {
                return i
            }
        }
        return -1
    }
    
    console.log(players.sx_findIndex(item => item.name === '科比')) // 0
    console.log(players.sx_findIndex(item => item.name === '安东尼')) // -1
    

     

    8、find

    参数代表含义

    • item:遍历项
    • index:遍历项的索引
    • arr:数组本身
    Array.prototype.sx_find = function (callback) {
        for (let i = 0; i < this.length; i++) {
            if (callback(this[i], i, this)) {
                return this[i]
            }
        }
        return undefined
    }
    
    console.log(players.sx_find(item => item.name === '科比')) // { name: '科比', num: 24 }
    console.log(players.sx_find(item => item.name === '安东尼')) // undefined
    

     

    9、fill

    用处:填充数组

    参数代表含义

    • initValue:填充的值
    • start:开始填充索引,默认0
    • end:结束填充索引,默认length - 1
    Array.prototype.sx_fill = function (value, start = 0, end) {
        end = (end || this.length - 1) + 1
        for (let i = start; i < end; i++) {
            this[i] = value
        }
        return this
    }
    
    console.log(players.sx_fill('林三心', 1, 3))
    // [
    //     { name: '科比', num: 24 },
    //     '林三心',
    //     '林三心',
    //     '林三心',
    //     { name: '杜兰特', num: 35 }
    // ]
    

     

    10、includes

    用处:查找元素,查到返回true,反之返回false,可查找NaN

    Array.prototype.sx_includes = function (value, start = 0) {
        if (start < 0) start = this.length + start
        const isNaN = Number.isNaN(value)
        for (let i = start; i < this.length; i++) {
            if (this[i] === value || Number.isNaN(this[i]) === isNaN) {
                return true
            }
        }
        return false
    }
    
    console.log([1, 2, 3].sx_includes(2)) // true
    console.log([1, 2, 3, NaN].sx_includes(NaN)) // true
    console.log([1, 2, 3].sx_includes(1, 1)) // false
    

      

     

    11、join

    用处:将数组用分隔符拼成字符串,分隔符默认为,

    Array.prototype.sx_join = function (s = ',') {
        let str = ''
        for(let i = 0; i < this.length; i++) {
            str = i === 0 ? `${str}${this[i]}` : `${str}${s}${this[i]}`
        }
        return str
    }
    
    console.log([1, 2, 3].sx_join()) // 1,2,3
    console.log([1, 2, 3].sx_join('*')) // 1*2*3
    

      

    12、flat

    Array.prototype.sx_flat = function () {
        let arr = this
        while (arr.some(item => Array.isArray(item))) {
            arr = [].concat(...arr)
        }
        return arr
    }
    
    const testArr = [1, [2, 3, [4, 5]], [8, 9]]
    
    console.log(testArr.sx_flat())
    // [1, 2, 3, 4, 5, 8, 9]
    

      

    Object篇

    定义一个测试对象

    const obj = {
        name: '林三心',
        age: 22,
        gender: '男'
    }
    

    13、entries

    用处:将对象转成键值对数组

    Object.prototype.sx_entries = function (obj) {
        const res = []
        for (let key in obj) {
            obj.hasOwnProperty(key) && res.push([key, obj[key]])
        }
        return res
    }
    
    console.log(Object.sx_entries(obj))
    // [ [ 'name', '林三心' ], [ 'age', 22 ], [ 'gender', '男' ] ]
    

    14、fromEntries

    用处:跟entries相反,将键值对数组转成对象

    Object.prototype.sx_fromEntries = function (arr) {
        const obj = {}
        for (let i = 0; i < arr.length; i++) {
            const [key, value] = arr[i]
            obj[key] = value
        }
        return obj
    }
    
    console.log(Object.sx_fromEntries([['name', '林三心'], ['age', 22], ['gender', '男']]))
    // { name: '林三心', age: 22, gender: '男' }
    

    15、keys

    用处:将对象的key转成一个数组合集

    Object.prototype.sx_keys = function (obj) {
        const keys = []
        for (let key in obj) {
            obj.hasOwnProperty(key) && res.push(key)
        }
        return keys
    }
    
    console.log(Object.keys(obj))
    // [ 'name', 'age', 'gender' 
    ]

      

    
    

    16、values

    用处:将对象的所有值转成数组合集

    Object.prototype.sx_values = function (obj) {
        const values = []
        for (let key in obj) {
            obj.hasOwnProperty(key) && values.push(obj[key])
        }
        return values
    }
    
    console.log(Object.sx_values(obj))
    // [ '林三心', 22, '男' ]
    

      

    17、instanceOf

    用处:A instanceOf B,判断A是否经过B的原型链

    function instanceOf(father, child) {
        const fp = father.prototype
        var cp = child.__proto__
    
        while (cp) {
            if (cp === fp) {
                return true
            }
            cp = cp.__proto__
        }
    
        return false
    }
    
    function Person(name) {
        this.name = name
    }
    const sx = new Person('林三心')
    
    console.log(instanceOf(Person, sx)) // true
    console.log(instanceOf(Person, sx2)) // false
    

      

    18、is

    用处:Object.is(a, b),判断a是否等于b

    Object.prototype.sx_is = function (x, y) {
        if (x === y) {
            // 防止 -0 和 +0
            return x !== 0 || 1 / x === 1 / y
        }
    
        // 防止NaN
        return x !== x && y !== y
    }
    
    const a = { name: '林三心' }
    const b = a
    const c = { name: '林三心' }
    
    console.log(Object.sx_is(a, b)) // true
    console.log(Object.sx_is(a, c)) // false
    

      

     

    Function篇

    19、call

    Function.prototype.sx_call = function (obj, ...args) {
        obj = obj || window
    
        // Symbol是唯一的,防止重名key
        const fn = Symbol()
        obj[fn] = this
    
        // 执行,返回执行值
        return obj[fn](...args)
    }
    
    const testobj = {
        name: '林三心',
        testFn(age) {
            console.log(`${this.name}${age}岁了`)
        }
    }
    const testobj2 = {
        name: 'sunshine_lin'
    }
    
    testobj.testFn.sx_call(testobj2, 22) // sunshine_lin22岁了

    20、apply

    Function.prototype.sx_apply = function (obj, args) {
        obj = obj || window
    
        // Symbol是唯一的,防止重名key
        const fn = Symbol()
        obj[fn] = this
    
        // 执行,返回执行值
        return obj[fn](...args)
    }
    
    const testobj = {
        name: '林三心',
        testFn(age) {
            console.log(`${this.name}${age}岁了`)
        }
    }
    const testobj2 = {
        name: 'sunshine_lin'
    }
    
    testobj.testFn.sx_apply(testobj2, [22]) // sunshine_lin22岁了
    

    String篇

    21、slice

    参数代表含义

    • start:开始截取的字符索引(包含此字符)
    • end:结束截取的字符索引(不包含此字符)

    注意点

    • start > end:返回空字符串
    • start < 0:start = 数组长度 + start
    String.prototype.sx_slice = function (start = 0, end) {
        start = start < 0 ? this.length + start : start
        end = !end && end !== 0 ? this.length : end
    
        if (start >= end) return ''
        let str = ''
        for (let i = start; i < end; i++) {
            str += this[i]
        }
    
        return str
    }
    
    console.log(str.sx_slice(2)) // nshine_lin
    console.log(str.sx_slice(-2)) // in
    console.log(str.sx_slice(-9, 10)) // shine_l
    console.log(str.sx_slice(5, 1)) // ''
    

    22、substr

    参数代表含义

    • start:开始截取的字符索引(包含此字符)
    • length:截取的长度

    注意点

    • start < 0:start = 数组长度 + start
    • length超出所能截取范围,需要做处理
    • length < 0:返回空字符串
    String.prototype.sx_substr = function (start = 0, length) {
        if (length < 0) return ''
    
        start = start < 0 ? this.length + start : start
        length = (!length && length !== 0) || length > this.length - start ? this.length : start + length
    
        let str = ''
        for (let i = start; i < length; i++) {
            str += this[i]
        }
        return str
    }
    
    console.log(str.sx_substr(3)) // shine_lin
    console.log(str.sx_substr(3, 3)) // shi
    console.log(str.sx_substr(5, 300)) // ine_lin
    

     

    23、substring

    功能与slice大致相同

    区别之处

    • start > end:互换值
    String.prototype.sx_sunstring = function (start = 0, end) {
        start = start < 0 ? this.length + start : start
        end = !end && end !== 0 ? this.length : end
    
        if (start >= end) [start, end] = [end, start]
        let str = ''
        for (let i = start; i < end; i++) {
            str += this[i]
        }
    
        return str
    }
    
    console.log(str.sx_sunstring(2)) // nshine_lin
    console.log(str.sx_sunstring(-2)) // in
    console.log(str.sx_sunstring(-9, 10)) // shine_l
    console.log(str.sx_sunstring(5, 1)) // unsh
    

     

    Promise篇

    24、all

    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 如果所有Promise都成功,则返回成功结果数组
    • 如果有一个Promise失败,则返回这个失败结果
     function all(promises) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                const addData = (index, value) => {
                    result[index] = value
                    count++
                    if (count === promises.length) resolve(result)
                }
                promises.forEach((promise, index) => {
                    if (promise instanceof MyPromise) {
                        promise.then(res => {
                            addData(index, res)
                        }, err => reject(err))
                    } else {
                        addData(index, promise)
                    }
                })
            })
        }
    

      

     

    25、race

    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 哪个Promise最快得到结果,就返回那个结果,无论成功失败
      function race(promises) {
            return new MyPromise((resolve, reject) => {
                promises.forEach(promise => {
                    if (promise instanceof MyPromise) {
                        promise.then(res => {
                            resolve(res)
                        }, err => {
                            reject(err)
                        })
                    } else {
                        resolve(promise)
                    }
                })
            })
        }
    

      

     

    26、allSettled

    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 把每一个Promise的结果,集合成数组,返回
      function allSettled(promises) {
            return new Promise((resolve, reject) => {
                const res = []
                let count = 0
                const addData = (status, value, i) => {
                    res[i] = {
                        status,
                        value
                    }
                    count++
                    if (count === promises.length) {
                        resolve(res)
                    }
                }
                promises.forEach((promise, i) => {
                    if (promise instanceof MyPromise) {
                        promise.then(res => {
                            addData('fulfilled', res, i)
                        }, err => {
                            addData('rejected', err, i)
                        })
                    } else {
                        addData('fulfilled', promise, i)
                    }
                })
            })
        }
    

      

     

    27、any

    any与all相反

    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 如果有一个Promise成功,则返回这个成功结果
    • 如果所有Promise都失败,则报错
      function any(promises) {
            return new Promise((resolve, reject) => {
                let count = 0
                promises.forEach((promise) => {
                    promise.then(val => {
                        resolve(val)
                    }, err => {
                        count++
                        if (count === promises.length) {
                            reject(new AggregateError('All promises were rejected'))
                        }
                    })
                })
            })
        }
    }
    

      

     

    困难篇

    28、Array.prototype.splice

    难点

    • 截取长度和替换长度的比较,不同情况
    Array.prototype.sx_splice = function (start, length, ...values) {
      length = start + length > this.length - 1 ? this.length - start : length
      const res = [], tempArr = [...this]
      for (let i = start; i < start + values.length; i++) {
        this[i] = values[i - start]
      }
      if (values.length < length) {
        const cha = length - values.length
        for (let i = start + values.length; i < tempArr.length; i++) {
          this[i] = tempArr[i + cha]
        }
        this.length = this.length - cha 
      }
      if (values.length > length) {
        for (let i = start + length; i < tempArr.length; i++) {
          this.push(tempArr[i])
        }
      }
      for (let i = start; i < start + length; i++) {
        res.push(tempArr[i])
      }
      return res
    }
    

     

    29、Object.assign

    难点

    • assign接收多个对象,并将多个对象合成一个对象
    • 这些对象如果有重名属性,以后来的对象属性值为准
    • assign返回一个对象,这个对象 === 第一个对象
    Object.prototype.sx_assign = function (target, ...args) {
        if (target === null || target === undefined) {
            throw new TypeError('Cannot convert undefined or null to object')
        }
        target = Object(target)
    
        for (let nextObj of args) {
            for (let key in nextObj) {
                nextObj.hasOwnProperty(key) && (target[key] = nextObj[key])
            }
        }
        return target
    }
    
    const testa = { name: '林三心' }
    const testb = { name: 'sunshine_lin', age: 22 }
    const testc = { age: 18, gender: '男' }
    
    const testd = Object.sx_assign(testa, testb, testc)
    console.log(testd) // { name: 'sunshine_lin', age: 18, gender: '男' }
    console.log(testa === testd) // true
    

     

    30、Function.prototype.bind

    难点:

    • bind是返回一个函数,而不是执行结果
    • bind返回的函数,拿来当做构造函数,该怎么处理
    Function.prototype.sx_bind = function (obj, ...args) {
        obj = obj || window
    
        // Symbol是唯一的,防止重名key
        const fn = Symbol()
        obj[fn] = this
        const _this = this
    
        const res = function (...innerArgs) {
            console.log(this, _this)
            if (this instanceof _this) {
                this[fn] = _this
                this[fn](...[...args, ...innerArgs])
                delete this[fn]
            } else {
                obj[fn](...[...args, ...innerArgs])
                delete obj[fn]
            }
        }
        res.prototype = Object.create(this.prototype)
        return res
    }
    

      



  • 相关阅读:
    MyBatis学习之输入输出类型
    MyBatis学习之多表查询
    javascript学习之this
    Elasticsearch学习之Java操作1
    CSS学习之定位
    CSS学习之浮动
    CSS学习之盒子模型
    java学习之导出Excel
    转载:手把手教你做iOS推送
    拳头公司聊天服务架构:服务器篇
  • 原文地址:https://www.cnblogs.com/ygunoil/p/15211702.html
Copyright © 2020-2023  润新知