有谁看过js的这种写法,为什么要这么写啊?

此函数用来完成在判断特定时间内发生N次事件以后进行触发回调函数。
比如鼠标在短期内点击三次或者四次触发。
但是不懂为什么要用这么奇怪的写法,有哪位大神知道吗?

function inBetween(n, t, callback, context) {    
    var sb = [];
    sb.push("var that = arguments.callee; ")
    sb.push("var thisTime = new Date().getTime(); ")
    sb.push("var arr = that['ARR'];");
    sb.push("if(!arr){");
    sb.push("    arr = []; ");
    sb.push("    for(var i = 0; i < that['N']; i++) arr.push(thisTime); ");
    sb.push("    that['ARR'] = arr;");
    sb.push("    that['COUNT']=0");
    sb.push("}");
    
    sb.push("that['COUNT']++; ");;
    sb.push("arr.push(thisTime);");
    sb.push("var lastTime = arr.shift();");
        
    sb.push("if(that['COUNT'] >= that['N']) {");
    sb.push("    that['COUNT']=1; ");
    sb.push("    for(var i = 0; i < that['N']; i++) arr[i] = thisTime; ");
    sb.push("    if(thisTime-lastTime < that['T']) ");          
    sb.push("        that['CB'].apply(that['CTX'], arguments); ");
    sb.push("}");
        
    var fn = new Function(sb.join(""));    
    fn['N']=n;
    fn['T']=t;
    fn['CB']=callback;
    fn['CTX']=context;
    return fn;        
}; 
1赞

这种方式可以动态生成代码

var sb=[];

这个足以说明这个程序员恨死这个项目了

1赞

不要轻易使用这种写法。所有使用new Function()或者eval()来实现的算法,都是可以使用普通写法来实现的。而使用new Function()或eval()来运行动态拼接的代码,会使JS引擎无法优化这些代码,造成运行效率下降。

大神如果不用这种写法应该怎么写呢?

第一次事件的时候 记录Date.now() 然后每触发一次就判断触发次数是否达到要求和与第一次触发时所记录的时间戳差值有没超时 同时通过这个判定后 回调 取消监听

function inBetween(n, t, callback, context) {
    var fn = function() {
        var that = arguments.callee;
        var thisTime = new Date().getTime();
        var arr = that['ARR'];
        if(!arr){
            arr = [];
            for(var i = 0; i < that['N']; i++) arr.push(thisTime);
            that['ARR'] = arr;
            that['COUNT']=0
        }

        that['COUNT']++;
        arr.push(thisTime);
        var lastTime = arr.shift();

        if(that['COUNT'] >= that['N']) {
            that['COUNT']=1;
            for(var i = 0; i < that['N']; i++) arr[i] = thisTime;
            if(thisTime-lastTime < that['T'])
                that['CB'].apply(that['CTX'], arguments);
        }
    }
    fn['N']=n;
    fn['T']=t;
    fn['CB']=callback;
    fn['CTX']=context;
    return fn;
};
1赞

谢谢,运行通过。再请问下这个 that[‘ARR’], that[‘CB’] 是什么写法?

就等价于that.ARR, that.CB

我简化了下,写成这样也是可以运行的。 不知道为啥要写那么复杂。

function inBetween(n, t, callback, context) {
	var ARR, COUNT;	
    return function fn () {
        var thisTime = new Date().getTime();
        var arr = ARR;
        if(!arr){
            arr = [];
            for(var i = 0; i < n; i++) arr.push(thisTime);
            ARR= arr;
            COUNT=0
        }

        COUNT++;
        arr.push(thisTime);
        var lastTime = arr.shift();

        if(COUNT>= n) {
            COUNT=1;
            for(var i = 0; i < n; i++) arr[i] = thisTime;
            if(thisTime-lastTime < t)
                callback.apply(context, arguments);
        }
    }
 
};

它的写法是为了不使用 eval,只使用 new Function 来生成方法,并且获取闭包内的变量。这样生成方法的效率会高一些,并且和 eval 一样不需要再多嵌套一个闭包。
使用 new Function 动态生成代码时,js 引擎无法进行优化,不过生成后的方法和普通方法没有任何区别,性能都是很优秀的。Creator 大量应用了 new Function 来动态生成方法体,这样相当于 JIT,可以大大优化性能。

谢谢jare大师的深入解答。