自定义函数工具库

目录

函数相关

call函数封装

apply函数封装

 bind函数封装

函数节流

函数防抖

数组相关

map函数封装

reduce函数封装

filter函数封装

find函数封装

findIndex函数封装

every函数封装

some函数封装

数组去重

双循环

利用对象

set结构

concat数组合并

slice数组切片

数组扁平化

递归实现

some+concat

   数组分块

数组差集

删除数组元素

获取数组的部分元素

得到当前过滤左边count个后剩余元素组成的数组

得到当前过滤右边count个后剩余元素组成的数组

对象相关

创建新对象

比对对象类型

对象合并

对象数组深浅拷贝

浅拷贝一

浅拷贝二

深拷贝之JSON转换

递归拷贝

深拷贝之解决循环引用

字符串方法

事件委托函数封装

事件总线

消息发布与订阅

axios封装


函数相关

call函数封装

语法call『 fn:要执行的函数 obj改变的this指向 ...args形参 』

功能执行fn,使this为obj,并将后面的n个参数传递给fn『等同于函数对象的call方法』

 function call(fn, obj, ...args) {
        if(obj===undefined||obj===null){
            obj=globalThis
        }
        obj.temp = fn
        let result=obj.temp(...args)
        delete obj.temp
        return result
    }

apply函数封装

语法apply『 fn:要执行的函数 obj改变的this指向 args形参 』

功能执行fn,使this为obj,并args数组中的参数传递给fn『等同于函数对象的apply方法』

function apply(fn, obj, args) {
        if(obj===undefined||obj===null){
            obj=globalThis
        }
        obj.temp = fn
        let result=obj.temp(...args)
        delete obj.temp
        return result
    }

 bind函数封装

语法bind『 fn:要执行的函数 obj改变的this指向 ...args形参 』

给fn绑定this为obj,并指定参数为后面的n个参数

 function call(fn, obj, ...args) {
        if (obj === undefined || obj === null) {
            obj = globalThis
        }
        obj.temp = fn
        let result = obj.temp(...args)
        delete obj.temp
        return result
    }
    function bind(fn, obj, ...args) {
        return function (...args2) {
            return call(fn, obj, ...args, ...args2)
        }
    }

函数节流

在函数需要频繁触发时,函数执行一次后,只有大于设定的周期后才会执行第二次

抢购疯狂点击,页面滚动,dom元素的拖拽 窗口调整,降低触发频率

    function throttle(callback, wait) {
        let start = 0
        return function (e) {
            let now = Date.now()
            if (now - start >= wait) {
                //this指向事件源
                callback.call(this, e)
                start = now
            }
        }
    }

函数防抖

在函数频繁触发时,在规定时间内只让最后一次生效

input框输入

function debounce(callback,time){
    let timeId=null
    return function(e){
        if(time!==null){
            clearTimeout(timeId)
        }
        timeId=setTimeout(()=>{
            callback.call(this,e)
            timeId=null
        },time)
    }
}

数组相关

map函数封装

方法创建一个新数组,其结果是该数组中的每个元素,调用一次提供的函数后的返回值

 @param{Array} arr

 @param{Function}  callback

    function map(arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            result.push(callback(arr[i], i))
        }
        return result
    }

reduce函数封装

从左到右为每一个元素执行一次回调函数,并把上一次回调函数的返回值放在一个暂存器中传给下一次回调,并返回最后一次函数的返回值

 @param{Array} arr

 @param{Function}  callback

@param{*}  initValue

    function reduce(arr, callback, initValue) {
        let result = initValue
        for (let i = 0; i < arr.length; i++) {
            result = callback(result, arr[i])
        }
        return result
    }

filter函数封装

把所有过滤函数中返回true的数组元素放到一个新数组中返回

 @param{Array} arr

 @param{Function}  callback

   let arr = [1, 2, 3, 4, 5]
    function filter(arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            let res = callback(arr[i], i)
            if (res) {
                result.push(arr[i])
            }

        }
        return result
    }

find函数封装

找到一个满足测试函数的第一个元素并返回那个元素的值,没有找到就是undefined

 @param{Array} arr

 @param{Function}  callback

function find(arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            let res = callback(arr[i], i)
            if (res) {
                return arr[i]
            }

        }
        return undefined
    }

findIndex函数封装

找到一个满足测试函数的第一个元素并返回那个元素的索引,没有找到就是-1

 @param{Array} arr

 @param{Function}  callback

    function findIndex(arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            let res = callback(arr[i], i)
            if (res) {
                return i
            }

        }
        return -1
    }

every函数封装

如果数组中每个元素都满足测试函数则返回true否则返回false

 @param{Array} arr

 @param{Function}  callback

    function every(arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            if (!callback(arr[i], i)) {
                return false
            }

        }
        return true
    }

some函数封装

如果数组中至少有一个元素满足测试函数则返回true否则返回false

 @param{Array} arr

 @param{Function}  callback

   function some(arr, callback) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            if (callback(arr[i], i)) {
                return true
            }

        }
        return false
    }

数组去重

双循环

    function unique(arr, callback) {
        let result = []
        arr.forEach(item => {
            if (result.indexOf(item) === -1) {
                result.push(item)
            }
        });
        return result
    }

利用对象

    let arr = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
    function unique(arr, callback) {
        let result = []
        let obj = {}
        arr.forEach(item => {
            if (obj[item] === undefined) {
                obj[item] = true
                result.push(item)
            }
        });
        return result
    }

set结构

    function unique(arr, callback) {

        return [...new Set(arr)]
    }

concat数组合并

扩展运算符(spread)用三个点号表示,功能是把数组或类数组对象展开成一系列用逗号隔开的值。

剩余运算符(rest)也是三个点号,不过其功能与扩展运算符恰好相反,把逗号隔开的值序列组合成一个数组。

    function concat(arr, ...args) {
        let result = [...arr]
        args.forEach(item => {
            if (Array.isArray(item)) {
                result.push(...item)
            } else {
                result.push(item)
            }
        })
        return result
    }

slice数组切片

返回一个截取后的新数组 ,含头不含尾

   function slice(arr, begin, end) {
        if (arr.length == 0) {
            return []
        }
        begin = begin || 0
        if (begin >= arr.length) {
            return []
        }
        end = end || arr.length
        if (end < begin) {
            end = arr.length
        }
        let result = []
        for (let i = 0; i < arr.length; i++) {
            if (i >= begin && i < end) {
                result.push(arr[i])
            }

        }
        return result
    }

数组扁平化

递归实现

    let arr = [1, 2, [3, 4, [5, 6]], 7]
    function flatten1(arr) {
        let result = []
        arr.forEach(item => {
            if (Array.isArray(item)) {
                result = result.concat(flatten1(item))
            } else {
                result = result.concat(item)
            }
        });
        return result
    }

some+concat

    let arr = [1, 2, [3, 4, [5, 6]], 7]
    function flatten2(arr) {
        let result = [...arr]
        while (result.some(item => Array.isArray(item))) {
            result = [].concat(...result)
        }

        return result
    }
    console.log((flatten2(arr)));

   数组分块

、将数组拆成多个size的区块每个区块组成小数组,整体组成一个二维数组

  let arr = [1, 2, 3, 4, 5, 6, 7]
    function chunk(arr, size = 1) {
        if (arr.length == 0) {
            return []
        }
        let result = []
        let temp = []
        arr.forEach(item => {
            if (temp.length === 0) {
                result.push(temp)
            }
            temp.push(item)
            if (temp.length === size) {
                temp = []
            }
        });
        return result
    }
    (chunk(arr, 3));

数组差集

得到数组中所有不在arr中的元素组成的数组

    let arr = [1, 2, 3, 4, 5, 6, 7]
    function difference(arr1, arr2 = []) {
        if (arr1.length == 0) {
            return []
        }
        if (arr2.length == 0) {
            return arr1.slice()
        }
        const result = arr1.filter(item => !arr2.includes(item))
        return result
    }
    console.log(difference(arr, [1, 2]));

删除数组元素

    let arr = [1, 2, 3, 4, 5, 6, 7]
    function pull(arr, ...args) {
        let result = []
        for (let i = 0; i < arr.length; i++) {
            if (args.includes(arr[i])) {
                result.push(arr[i])
                arr.splice(i, 1)
                i--
            }
        }
        return result
    }
    function pullAll(arr, value) {
        return pull(arr, ...value)
    }

    console.log(pull(arr, 1, 2, 3));
    console.log(arr);

获取数组的部分元素

得到当前过滤左边count个后剩余元素组成的数组

 let arr = [1, 2, 3, 4, 5, 6, 7]
    function drop(arr, size) {
        return arr.filter((item, index) => index >= size)
    }
    console.log(drop(arr, 2));

得到当前过滤右边count个后剩余元素组成的数组

    let arr = [1, 2, 3, 4, 5, 6, 7]
    function drop(arr, size) {
        return arr.filter((item, index) => index < arr.length - size)
    }
    console.log(drop(arr, 2));

对象相关

创建新对象

创建一个新对象  this指向这个新对象  修改新对象的原型对象

如果是基本数据类型返回新对象 复杂数据类型返回返回值

    function Person(name, age) {
        this.name = name
        this.age = age
    }
    function newInstance(Fn, ...args) {
        const obj = {}
        const result = Fn.call(obj, ...args)
        obj.__proto__ = Fn.prototype
        return result instanceof Object ? result : obj
    }
    let obj = newInstance(Person, 'zs', 18)
    console.log(obj);

比对对象类型

    function Person(name, age) {
        this.name = name
        this.age = age
    }
    let obj = new Person
    function myInstanceOf(obj, fn) {
        let prototype = fn.prototype
        let proto = obj.__proto__
        while (proto) {
            if (prototype === proto) {
                return true
            }
            proto = proto.__proto__
        }
        return false
    }
    console.log(myInstanceOf(obj, Function));

对象合并

   let object = {
        a: [{ x: 2 }, { y: 4 }],
        b: 1
    }
    let other = {
        a: { z: 3 },
        b: [2, 3],
        c: 'foo'
    }
    function merageObject(...objs) {

        const result = []
        objs.forEach(obj => {
            Object.keys(obj).forEach(key => {
                if (result.hasOwnProperty(key)) {
                    result[key] = [].concat(result[key], obj[key])
                } else {
                    result[key] = obj[key]
                }
            })
        })
        return result
    }
    console.log(merageObject(object, other));

对象数组深浅拷贝

浅拷贝一

只克隆了对象属性和数组元素本身(只是引用地址的值)

    let object = {
        a: { y: 4 },
        b: 1
    }
    function clone1(target) {
        if (typeof target == "object" && target !== null) {
            if (Array.isArray(target)) {
                return [...target]
            } else {
                return { ...target }
            }
        } else {
            return target
        }
    }
    const result = clone1(object)
    result.a.y = 5
    console.log(object, result);

浅拷贝二

hasOwnProperty表示是否有自己的属性。这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链。

for循环 只可以遍历数组  for of 只能遍历有迭代器的 for in 会遍历原型上的

    let object = {
        a: { y: 4 },
        b: 1
    }
    function clone2(target) {
        if (typeof target == "object" && target !== null) {
            let result = Array.isArray(target) ? [] : {}
            for (const key in target) {
                if (target.hasOwnProperty(key)) {
                    result[key] = target[key]
                }
            }
            return result
        }
    }
    const res = clone2(object)
    res.a.y = 5
    console.log(object, res);

深拷贝之JSON转换

不能克隆 函数 及循环引用

    let object = {
        a: { y: 4 },
        b: 1
    }
    function deepClone1(target) {

        let str = JSON.stringify(target)
        let result = JSON.parse(str)
        return result
    }
    const res = deepClone1(object)
    res.a.y = 5
    console.log(object, res);

递归拷贝

 let object = {
        a: { y: 4 },
        b: ['e', 'f', 'g'],
        c: { h: 20 },
        d: function () { }
    }
    function deepClone2(target) {
        if (typeof target == "object" && target !== null) {
            let result = Array.isArray(target) ? [] : {}
            for (const key in target) {
                if (target.hasOwnProperty(key)) {
                    result[key] = deepClone2(target[key])
                }
            }
            return result
        } else {
            return target
        }

    }
    const res = deepClone2(object)
    res.a.y = 5000
    console.log(object, res);

深拷贝之解决循环引用

   let object = {
        a: { y: 4 },
        b: ['e', 'f', 'g'],
        c: { h: 20 },
        d: function () { }
    }
    function deepClone3(target, map = new Map()) {
        if (typeof target == "object" && target !== null) {
            let cache = map.get(target)
            if (cache) {
                return cache
            }
            let isArray = Array.isArray(target)
            let result = isArray ? [] : {}
            map.set(target, result)
            if (isArray) {
                target.forEach((item, index) => {
                    result[index] = deepClone3(item, map)
                })
            } else {
                Object.keys(target).forEach(key => {
                    result[key] = deepClone3(target[key], map)
                })
            }
            return result
        } else {
            return target
        }

    }
    object.b.push(object.c)
    object.c.j = object.b
    const res = deepClone3(object)

    res.a.y = 5000
    console.log(object, res);

字符串方法

反转  检测回文  截取

   let str = 'IloveYou'
    str2 = 'lol'
    str3 = '[字符串方法测试] 努力学习 天天向上'
    function reverseString(str) {
        let arr = [...str]
        arr.reverse()
        let s = arr.join('')
        return s
    }
    function palindroms(str) {
        return reverseString(str) === str
    }
    function truncate(str, size) {
        return str.slice(0, size) + '...'
    }
    console.log(reverseString(str));
    console.log(palindroms(str3));
    console.log(truncate(str3, 10));

事件委托函数封装

  •      @param{Element} el 父级元素
  •      @param{event}type 事件类型
  •      @param{Function}fn
  •      @param{Element} selector 子级元素

matches :

主要是用来判断当前DOM节点是否能完全匹配对应的CSS选择器规则;如果匹配成功,返回true,反之则返回false。

 <ul id="items">
    <li>aaa</li>
    <li>bbb</li>
    <li>ccc</li>
    <li>ddd</li>
    <div>eee</div>
</ul>
function addEventListener(el, type, fn, selector) {
        if (typeof el == "string") {
            el = document.querySelector(el)
        }
        if (!selector) {
            el.addEventListener(type, fn)
        } else {
            el.addEventListener(type, function (e) {
                const target = e.target
                if (target.matches(selector)) {
                    fn.call(target, e)
                }
            })
        }
    }
    addEventListener('#items', 'click', function (e) {
        console.log(this.innerHTML);
    }, 'li')

事件总线

  const eventBus = {
        callback: {
            // login: [fn, fn2]
        }
    }
    eventBus.on = function (type, callback) {
        if (this.callback[type]) {
            this.callback[type].push(callback)
        } else {
            this.callback[type] = [callback]
        }
    }

    eventBus.emit = function (type, data) {
        if (this.callback[type] && this.callback[type].length > 0) {
            this.callback[type].forEach(callback => {
                callback(data)
            });
        }

    }
    eventBus.off = function (eventName) {
        if (eventName) {
            delete this.callback[eventName]
        } else {
            this.callback = {}
        }
    }

    eventBus.on('login', data => {
        console.log(data + '用户已经登录');
    })
    eventBus.on('login', data => {
        console.log(data + '用户信息已经写入');
    })
    eventBus.on('outlogin', data => {
        console.log(data + '用户已经退出');
    })
    console.log(eventBus);
    setTimeout(() => {
        eventBus.emit('login', 'zs')
        eventBus.emit('outlogin', 'zs')
    }, 2000)
    // eventBus.off()

消息发布与订阅

    const PubSub = {
        id: 1,
        callback: {
            // pay: {
            //     token_1: fn,
            //     token_2: fn
            // }
        }
    }
    //订阅
    PubSub.subscribe = function (type, callback) {
        let token = 'token_' + this.id++
        if (this.callback[type]) {
            this.callback[type][token] = callback
        } else {
            this.callback[type] = {
                [token]: callback
            }
        }
        return token
    }
    //发布
    PubSub.publish = function (type, data) {
        if (this.callback[type]) {
            Object.values(this.callback[type]).forEach(callback => {
                callback(data)
            })
        }
    }
    // 取消
    PubSub.unsubscribe = function (flag) {
        if (flag == undefined) {
            this.callback = {}
        } else if (typeof flag === "string") {
            if (flag.indexOf('token_') == 0) {
                let callbackobj = Object.values(this.callback).find(obj => obj.hasOwnProperty(flag))
                if (callbackobj) {
                    delete callbackobj[flag]
                }
            } else {
                delete this.callback[flag]
            }
        }
    }
    let pid1 = PubSub.subscribe('pay', data => {
        console.log('商家接到了订单,准备开始制作', data);
    })
    let pid2 = PubSub.subscribe('pay', data => {
        console.log('骑手接到订单,准备开始取餐', data);
    })
    PubSub.subscribe('cancel', data => {
        console.log('商家接到了取消请求', data);
    })
    PubSub.publish('pay', { title: '饺子' })
    PubSub.unsubscribe(pid2)
    console.log(PubSub);

axios封装

 function axios({ method, url, params, data }) {
        method = method.toUpperCase()

        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest()
            let str = ''
            for (const k in params) {
                str += `${k}=${params[k]}&`
            }
            str = str.slice(0, -1)
            xhr.open(method, url + '?' + str)
            if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
                xhr.setRequestHeader('Content-type', 'application/json')

                xhr.send(JSON.stringify(data))
            } else {
                xhr.send()
            }
            xhr.responseType = 'json'
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        resolve({
                            status: xhr.status,
                            message: xhr.statusText,
                            body: xhr.response
                        })
                    } else {
                        reject(new Error('请求失败,失败状态码为' + xhr.status))
                    }
                }
            }

        })
    }
    axios({
        method: 'POST',
        url: 'http://webapi.hanmaweilai.com/api/v1/postData',
        params: {
            a: 100,
            b: 200
        },
        data: {
            c: 300,
            d: 400
        }
    }).then((response) => {
        console.log(response);
    })


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值