zoukankan      html  css  js  c++  java
  • 常见的JS手写函数汇总(代码注释、持续更新)

    最近在复习面试中常见的JS手写函数,顺便进行代码注释和总结,方便自己回顾也加深记,内容也会陆陆续续进行补充和改善。

    一、手写深拷贝

        <script>
            const obj1 = {
                name: 'Leise',
                age: 23,
                address: {
                    country: 'China',
                    city: 'Guanzhou'
                }
            }
            const obj2 = deepClone(obj1)
            obj2.address.city = 'Hangzhou'
            console.log(obj1.address.city);
            console.log(obj2.address.city);
    ​
            function deepClone(obj) {
                //判断是否为非对象或者是null
                if (typeof obj !== 'object' || typeof pbj == null) {
                    return obj
                }
                // 初始化拷贝结果
                let result
                // 判断是数组还是对象
                if (obj instanceof Array) {
                    result = []
                } else {
                    result = {}
                }
                for (let key in obj) {
                 //保证key不是原型的属性
                    if (obj.hasOwnProperty(key)) {
                 //  递归调用深拷贝 防止多重嵌套
                        result[key] = deepClone(obj[key])
                    }
                }
                // 最后返回结果 
                return result
            }
        </script>
    ​

    二、手写bind函数

    <script>
        Function.prototype.mybind = function () {
            //原型添加方法mybind
            const args = Array.prototype.slice.call(arguments)
            //将获得参数拆解成数组
            const t = args.shift()
            //获取this(数组第一项,同时剔除第一项,shift可以实现)
            const self = this
            //当前fn1.bind(...)中的fn1
            //console.log(this);
            //function fn1(a, b, c) {
            //console.log("this", this);
             //定义一个变量保留this指向
            //console.log(a, b, c);  }
            return function () {
                //console.log(this);window
                return self.apply(t, args)
                //这个函数需要执行
            }
        }
    ​
        function fn1(a, b, c) {
            console.log("this", this);
            console.log(a, b, c);
    ​
        }
        const fn2 = fn1.mybind({
            x: 1,
            y: 2
        }, 10, 20, )
        //bind之后需要执行
        const res = fn2()
        //保存运行后的结果并打印出来
        console.log(res);
    </script>

    三、手写通用事件绑定函数

    <script>
        function bindEvent(elem, type, selcetor, fn) {
            //判断三个还是四个,四个则是事件代理
            if (fn == null) {
                fn = selcetor
                selcetor = null
            }
            //开始绑定事件
            elem.addEventListener(type, event => {
                const target = event.target
                //判断是事件代理还是普通绑定
                if (selector) {
                    //事件代理
                    if (target.matches(selcetor)) {
                        fn.call(target, event)
                    } else {
                        fn.call(target.event)
                    }
                }
    ​
            })
        }
    ​
        function bindEvent(elem, type, selector, fn) {
            // 三个参数和四个参数的判断处理
            if (fn == null) {
                fn = selector
                selector = null
            }
            elem.addEventListener(type, event => {
                const target = event.target
                if (selector) {
    ​
                    // 有selector就是代理
    if (target.matches(selector)) {
                        fn.call(target, event)
                    }
                } else {
                    fn.call(target, event)
                }
            })
        }
    ​
        const div3 = document.getElementById('div3')
        bindEvent(div3, 'click', 'a',
            function (event) {
                event.preventDefault()
                alert(this.innerHTML)
    ​
            })
    </script>

    四、手写闭包的简单应用

    <script>
        function createCache() {
            // 闭包隐藏数据,只提供 API
            let obj = {}
            return {
                set: function (key, value) {
                    obj[key] = value
                },
                get: function (key) {
                    return obj[key]
                }
            }
        }
        const c = createCache()
        c.set('a', 100)
        console.log(c.get('a'))
        obj.d = 100 //undefined,必须使用get或者set
    </script>

    五、手写promise

        <script>
            function loadImg(url) {
                return new Promise((resolve, reject) => {
                    const img = document.createElement('img')
                    img.src = url
                    img.onload = () => {
                        resolve(img)
                    }
                    img.onerror = () => {
                        reject(new Error("图片加载失败"))
                    }
                })
            }
            const url1 = 'http://img.mukewang.com/5e5c85e1000116c505400720-156-88.jpg'
            const url2 = 'https://img.mukewang.com/szimg/5dba8cee0969880506000338.jpg'
            loadImg(url1).then((img1) => {
                console.log(img1.width);
                return img1
            }).then((img1) => {
                console.log(img1.height);
                return loadImg(url2)
            }).then(img2 => {
                console.log(img2.width);
            })
        </script>

    六、手写Ajax

       <script>
            function ajax(url) {
                return new Promise((resolve, reject) => {
    ​
                    //判断谷歌等还是IE
                    let xhr
                    if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
                        xhr = new XMLHttpRequest()
    ​
                    } else { // code for IE6, IE5
                        xhr = new ActiveXObject("Microsoft.XMLHTTP")
                    }
                    // xhr 具有一个 open 方法,这个方法的作用类似于初始化,并不会发起真正的请求
                    // open 方法具有 5 个参数,但是常用的是前 3 个
                    // method: 请求方式 —— get / post
                    // url:请求的地址
                    // async:是否异步请求,默认为 true(异步)
                    xhr.open("get", url, true)
                    // send 方法发送请求,并接受一个可选参数
                    // 当请求方式为 post 时,可以将请求体的参数传入
                    // 当请求方式为 get 时,可以不传或传入 null
                    // 不管是 get 还是 post,参数都需要通过 encodeURIComponent               编码后拼接
                    xhr.send(null)
                    //当readyStatus的状态发生改变时,会触发 xhr 的事件onreadystatechange
                    xhr.onreadystatechange = () => {
                        //readyStatus: 请求/响应过程的当前活动阶段
                        if (xhr.readyState == 4) {
                        //HTTP 状态在 200-300 之间表示请求成功
                       // HTTP 状态为 304 表示请求内容未发生改变,可直接从缓存中读取
                            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
    ​
                                let obj = JSON.parse(xhr.responseText)
                                // console.log(obj)
                                // callBack(obj)
                                resolve(obj)
                            } else {
                                reject(new Error("错误"))
                            }
                        }
                    }
                })
            }
            const url1 = "http://jsonplaceholder.typicode.com/users"
            const url2 = "/a.json"
            const url3 = "/b.json"
    ​
            ajax(url1).then(res => {
                console.log(res);
                return ajax(url2)
            }).then(res => {
                console.log(res);
                return ajax(url3)
            }).then(() => {
                console.log("ok");
            }).catch((res) => {
                console.log(res) //设置一个统一出口 如果出现错误就终止
            })
        </script>

    七、手写防抖

       <script>
            const input1 = document.getElementById('input1')
    ​
            function debounce(fn, delay) {
                //timer必须在闭包中 才不会被外面修改
                let timer = null
                return function () {
                    if (timer) {
                        clearTimeout(timer)
                    }
                    timer = setTimeout(() => {
                        fn.apply(this, arguments)
                        timer = null
                    }, delay);
                }
            }
            input1.addEventListener('keyup', debounce(function () {
                console.log(input1.value);
            }, 500))
        </script>

    八、手写节流

    <script>
        function throttle(fn, delay) {
            let timer = null
            return function () {
                if (timer) {
                    return
                }
                timer = setTimeout(() => {
                    fn.apply(this, arguments)
                    timer = null++
                }, delay);
            }
        }
        const one = document.getElementById('one')
        one.addEventListener('drag', throttle(function (e) {
            console.log(e.offsetX, e.offsetY);
        }, 1000))
    </script>

     

  • 相关阅读:
    HPB 是什么
    HPB共识算法选举机制描述
    【CS231n】斯坦福大学李飞飞视觉识别课程笔记(六):线性分类笔记(上)
    大讲堂专访丨连接Oracle DBA与开发的桥梁:Oracle的redo与undo
    SCN风波又起,2019年6月之前Oracle必须升级吗?
    去面试Python工程师,这几个基础问题一定要能回答,Python面试题No4
    OpenStack 的单元测试
    创建docker镜像的两种方式
    Vue.js 条件渲染 v-if、v-show、v-else
    Linux下Wiki服务器的搭建
  • 原文地址:https://www.cnblogs.com/leise/p/13630124.html
Copyright © 2011-2022 走看看