继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

在JS中统计函数执行次数与执行时间

蝴蝶不菲
关注TA
已关注
手记 372
粉丝 81
获赞 381

假如想统计JS中的函数执行次数最多的是哪个,执行时间最长的是哪个,该怎么做呢?

 

1. 统计函数执行次数

2. 统计函数执行时间

3. 如何控制函数的调用次数

4. 如何控制函数的执行时间

 

一、统计函数执行次数

常规的方法可以使用 console.log 输出来肉眼计算有多少个输出

不过在Chrome中内置了一个 console.count 方法,可以统计一个字符串输出的次数。我们可以利用这个来间接地统计函数的执行次数

复制代码

function someFunction() {
    console.count('some 已经执行');
}function otherFunction() {
    console.count('other 已经执行');
}

someFunction(); // some 已经执行: 1someFunction(); // some 已经执行: 2otherFunction(); // other 已经执行: 1console.count(); // default: 1console.count(); // default: 2

复制代码

不带参数则为 default 值,否则将会输出该字符串的执行次数,观测起来还是挺方便的

 

当然,除了输出次数之外,还想获取一个纯粹的次数值,可以用装饰器将函数包装一下,内部使用对象存储调用次数即可

复制代码

var getFunCallTimes = (function() {    
    // 装饰器,在当前函数执行前先执行另一个函数
    function decoratorBefore(fn, beforeFn) {        return function() {            var ret = beforeFn.apply(this, arguments);            // 在前一个函数中判断,不需要执行当前函数
            if (ret !== false) {
                fn.apply(this, arguments);
            }
        };
    }    
    // 执行次数
    var funTimes = {};    
    // 给fun添加装饰器,fun执行前将进行计数累加
    return function(fun, funName) {        // 存储的key值
        funName = funName || fun;        
        // 不重复绑定,有则返回
        if (funTimes[funName]) {            return funTimes[funName];
        }        
        // 绑定
        funTimes[funName] = decoratorBefore(fun, function() {            // 计数累加
            funTimes[funName].callTimes++;

            console.log('count', funTimes[funName].callTimes);
        });        
        // 定义函数的值为计数值(初始化)
        funTimes[funName].callTimes = 0;        return funTimes[funName];
    }
})();

复制代码

复制代码

function someFunction() {
    
}function otherFunction() {
    
}


someFunction = getFunCallTimes(someFunction, 'someFunction');

someFunction(); // count 1someFunction(); // count 2someFunction(); // count 3someFunction(); // count 4console.log(someFunction.callTimes); // 4otherFunction = getFunCallTimes(otherFunction);
otherFunction(); // count 1console.log(otherFunction.callTimes); // 1otherFunction(); // count 2console.log(otherFunction.callTimes); // 2

复制代码

 

二、统计函数执行时间

Chrome中内置了 console.time 和 console.timeEnd 来打点计算时间

复制代码

console.time();for (var i = 0; i < 100000; ++i) {

}

console.timeEnd(); // default: 1.77197265625ms

复制代码

不传入参数的话,将以default输出毫秒值

我们可以封装一下,传入函数名称,类似上面的做法,使用装饰器在函数执行前后进行处理

复制代码

var getFunExecTime = (function() {    
    // 装饰器,在当前函数执行前先执行另一个函数
    function decoratorBefore(fn, beforeFn) {        return function() {            var ret = beforeFn.apply(this, arguments);            // 在前一个函数中判断,不需要执行当前函数
            if (ret !== false) {
                fn.apply(this, arguments);
            }
        };
    }    // 装饰器,在当前函数执行后执行另一个函数
    function decoratorAfter(fn, afterFn) {        return function() {
            fn.apply(this, arguments);
            afterFn.apply(this, arguments);
        };
    }    
    // 执行次数
    var funTimes = {};    
    // 给fun添加装饰器,fun执行前后计时
    return function(fun, funName) {        return decoratorAfter(decoratorBefore(fun, function() {            // 执行前            console.time(funName);
        }), function() {            // 执行后            console.timeEnd(funName);
        });
    }
})();

复制代码

那么调用的时候,就不需要理会如何计时了

复制代码

function someFunction() {    for (var i = 0; i < 100000; ++i) {

    }
}function otherFunction() {    for (var i = 0; i < 10000000; ++i) {

    }
}

someFunction = getFunExecTime(someFunction, 'someFunction');
someFunction(); // someFunction: 1.616943359375msotherFunction = getFunExecTime(otherFunction, 'otherFunction');
otherFunction(); // otherFunction: 18.157958984375ms

复制代码

 

Chrome的Console API毕竟不是标准的,除了使用它之外,还可以选择日期插件 Date 中的 getTime now 相关方法

然而使用Date对象来计算耗时并不正统,推荐使用标准的 performance.now

复制代码

var start = performance.now();

console.time();for (var i = 0; i < 10000000; ++i) {

}var end = performance.now();

console.timeEnd(); // default: 23.598876953125msconsole.log(end - start); // 23.600000015459955

复制代码

可以看到,它们是相差不大的

使用类似的方法,将它包装起来以便方便调用

复制代码

var getFunExecTime = (function() {    
    // 装饰器,在当前函数执行前先执行另一个函数
    function decoratorBefore(fn, beforeFn) {        return function() {            var ret = beforeFn.apply(this, arguments);            // 在前一个函数中判断,不需要执行当前函数
            if (ret !== false) {
                fn.apply(this, arguments);
            }
        };
    }    // 装饰器,在当前函数执行后执行另一个函数
    function decoratorAfter(fn, afterFn) {        return function() {
            fn.apply(this, arguments);
            afterFn.apply(this, arguments);
        };
    }    
    // 执行次数
    var funTimes = {};    
    // 给fun添加装饰器,fun执行前后计时
    return function(fun, funName) {
        funName = funName || fun;        if (funTimes[funName]) {            return funTimes[funName];
        }        
        // 绑定
        funTimes[funName] = decoratorAfter(decoratorBefore(fun, function() {            // 执行前
            funTimes[funName].timestampStart = performance.now();
        }), function() {            // 执行后
            funTimes[funName].timestampEnd = performance.now();            
            // 将执行耗时存入
            funTimes[funName].valueOf = function() {                return this.timestampEnd - this.timestampStart;
            };
        });        return funTimes[funName];
    }
})();

复制代码

复制代码

function someFunction() {    for (var i = 0; i < 100000; ++i) {

    }
}function otherFunction() {    for (var i = 0; i < 10000000; ++i) {

    }
}// 包装someFunction = getFunExecTime(someFunction);// 执行someFunction();// 获取耗时,可直接使用函数的 valueOfconsole.log(+someFunction); // 2.0999999847263098otherFunction = getFunExecTime(otherFunction, 'otherFunction');
otherFunction(); 
console.log(+otherFunction); // 21.00000000745058

复制代码

 

三、如何控制函数的调用次数

也可以通过闭包来控制函数的执行次数

复制代码

function someFunction() {
    console.log(1);
}function otherFunction() {
    console.log(2);
}function setFunCallMaxTimes(fun, times, nextFun) {    return function() {        if (times-- > 0) {            // 执行函数
            return fun.apply(this, arguments);
        } else if (nextFun && typeof nextFun === 'function') {            // 执行下一个函数
            return nextFun.apply(this, arguments);
        }
    };
}var fun = setFunCallMaxTimes(someFunction, 3, otherFunction);

fun(); // 1fun(); // 1fun(); // 1fun(); // 2fun(); // 2

复制代码

 

四、如何控制函数的执行时间

因为JS是单线程的,控制函数的执行时间相对来说挺麻烦

通过 async await yield 等异步特性,也许还是能办到的

在React 16中的 Fiber 机制,在某种意义上是能控制函数的执行时机,得空再去看看它是怎么实现的吧

[-_-]眼睛累了吧,注意劳逸结合呀[-_-]

原文出处:https://www.cnblogs.com/imwtr/p/9582150.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP