函数技巧总结

记录一些实用的函数技巧

  包含大量实用函数,持续更新中。

1、尤大的强绑bind实现(据说比原生还快一点)

    //传入强绑函数与上下文
    function bind(fn, ctx) {
        function boundFn(a) {
            var l = arguments.length;
            //根据传参数执行函数
            return l ?
                l > 1 ?
                fn.apply(ctx, arguments) :
                fn.call(ctx, a) :
                fn.call(ctx)
        }
        //保存传入函数形参数
        boundFn._length = fn.length;
        return boundFn
    }
    //示例
    var obj = {
        a: 1
    }
    var fn = bind(function(n1, n2) {
        console.log(this.a);
        console.log(n1 + n2);
    }, obj);
    fn(1, 2); //1 3

  使用方法也很简答,传入函数与强绑上下文,再传入参数执行。

2、事件触发节流阀

  该方法来源于伟大的jQuery作者,john ***!

    // 节流函数与最低触发事件
    function delayFn(fn, delay) {
        var timer = false;
        // 滚动触发
        window.onscroll = function() {
            timer = true;
        };
        // 每隔一段时间触发指定函数
        setInterval(function() {
            if (timer) {
                timer = false;
                fn();
            }
        }, delay);
    }

  这个函数也相当简单,用于滚动事件的监听。由于滚动会非常频繁的触发onscroll,所以设定一个触发频率可以极大的优化浏览器性能。

3、缓步加载函数

  该函数应用场景主要是后台提供了大量的数据需要渲染到页面,然而直接拼接字符串+innerHTML会导致假卡死,用户体验极差。

  虽然说这个问题的源头就是错误的,但是也有一些补救的办法。

    // 假设通过ajax请求到一个包含大量数据的数组
    ajax('url', function(result) {
        var data = result;
        fps(data, 1000, 1000, function(data) {
            console.log(data);
        });
    });
    // cut为每次处理的数量
    // delay为每次处理的间隔时间
    function fps(data, cut, delay, fn) {
        // 对剩余数量做检测
        var res = data.length < cut ? data.splice(0, data.length) : data.splice(0, cut);
        fn(res);
        if (data.length > 0) {
            // 下一批数据的处理会在下一个task中进行
            setTimeout(fps, delay);
        }
    }

  自己手写的,比较简单,大概思想出来就好了嘛~

4、插入一个深拷贝函数

    // 接受变量与类型
    function type(el, type) {
        return Object.prototype.toString.call(el).slice(8, -1) === type;
    }
    // 深拷贝 目标对象与拷贝对象
    function deepCopy(tar, obj) {
        var tar = tar || {},
            el, clone;
        for (var key in obj) {
            el = obj[key];
            if (type(el, 'Object') || type(el, 'Array')) {
                clone = type(el, 'Object') ? {} : [];
                tar[key] = deepCopy(clone, el);
            } else {
                tar[key] = el;
            }
        }
        return tar;
    }
    // 使用方法
    var obj = {
        a: [1],
        b: {
            a: 1
        }
    };
    var obj2 = {};
    deepCopy(obj2, obj);

5、数组去重

  来自于jQuery源码:

    // 去重
    function duplicate(arr) {
        var len = arr.length,
            num = 0,
            res = [];
        // 先进行排序
        arr.sort((a, b) => a - b);
        // 找出所有相邻重复元素索引
        for (var i = 0; i < len; i++) {
            if (arr[i] === arr[i + 1]) {
                res.push(i);
                num++;
            }
        }
        //依次删除
        while (num--) {
            arr.splice(res[num], 1);
        }
        return arr;
    }

 6、数组乱序

  打乱数组,俗称洗牌,方法超级简单易懂,但是可能很low。没关系!可以多循环几次!

    // 返回随机数
    function getR(len) {
        return Math.floor(Math.random() * len);
    }
    // 打乱数组
    function randomArr(arr) {
        var len = arr.length,
            j;
        for (var i = 0; i < len; i++) {
            // 获取随机索引
            j = getR(len);
            // 交换位置
            [arr[i], arr[j]] = [arr[j], arr[i]];
        }
        return arr;
    }

 

 7、缓存函数

  来源于vue源码:

    // 有时候可能需要默认缓存对象
    function cached(fn, cache) {
        var cache = cache || Object.create(null);
        // 返回一个函数
        return (function cachedFn(str) {
            var hit = cache[str];
            return hit || (cache[str] = fn(str))
        })
    }

  默认情况下创建一个纯净对象用来做缓存,当然也可以选择自己传入一个带有默认值得缓存对象。

8、惰性求值函数

  适用于兼容性判断,第一次加载重写函数,第二次跳过判断逻辑。

    var a = 1;
    // 惰性加载函数
    function lazy(el) {
        // 第一次做判断
        if (el === 1) {
            // 然后重写函数
            lazy = function() {
                return 1;
            }
        } else if (el === 2) {
            lazy = function() {
                return 2;
            }
        }
        return lazy();
    }
    console.log(lazy(a)); //1
    // 第二次调用跳过判断环节
    console.log(lazy(a)); //1
    console.log(lazy(a)); //1
    console.log(lazy(a)); //1
    console.log(lazy(a)); //1

  

 9、遍历DOM树

  超级简单!!!一看就会

    // 遍历DOM树
    function walkDom(node, fn) {
        fn(node);
        // 使用该方法避免回车会导致空行 
        node = node.firstElementChild;
        while (node) {
            walkDom(node, fn);
            node = node.nextElementSibling;
        }
    }
    // 示例
    var div = document.getElementsByTagName('div')[0];
    walkDom(div, function(el) {
        console.log(el.tagName);
    });

 

10、快速生成16进制颜色

  超级简单!!!

    function getHexColor() {
        return '#' + Math.random().toString(16).substr(2, 6);
    }

  先写这几个了!

原文地址:https://www.cnblogs.com/QH-Jimmy/p/6566099.html