everycode icon indicating copy to clipboard operation
everycode copied to clipboard

2014年11月20日

Open nunnly opened this issue 10 years ago • 13 comments

console.log这个是我们经常调试页面的时候用的工具,但是有时候呢,我们只需要这个日志只输出一次(通常出现在node上),实现以下需求: 完成一个函数,函数接收一个参数function,执行完了之后第二次就失效~~~ 么么哒,今天开会改BUG,忙疯了!!!

function once(fn){
    return fn
}

logOnce = once(console.log)
logOnce("foo") // -> "foo"
logOnce("bar") // -> no effect

nunnly avatar Nov 20 '14 03:11 nunnly

function once(fn){ var a = 0; return function(){ if(a != 0)return "no effect"; a=1; fn.apply(this,arguments) } }

logOnce = once(alert); logOnce("foo") ; logOnce("bar") ;

jiehe avatar Nov 20 '14 03:11 jiehe

function once(fn) {
    var l = undefined;
    return function() {
        return !l ? fn.apply((l = 1) && null, arguments) : "no effect";
    };
}

logOnce = once(console.log)
logOnce("foo") // -> "foo"
logOnce("bar") // -> no effect

var a = [1,2];
var func = once(function(i) { console.log(this[i]); }.bind(a));
func(1);
func(0);

XadillaX avatar Nov 20 '14 04:11 XadillaX

上一个无 var,并且除了内嵌的匿名函数以外整个函数实现只有一条语句的实现:

function once(fn) {
    return !((this.l ? this.l : (this.l = [])).push({ f: function() {
        return this.used ? "no effect" : fn.apply((this.used = true) && null, arguments);
    }, used: false })) || this.l[this.l.length - 1].f.bind(this.l[this.l.length - 1]);
}

XadillaX avatar Nov 20 '14 05:11 XadillaX

简化上面的做法:

function once(fn) {
    return function() {
        return this.u ? "no effect" : fn.apply((this.u = 1) && null, arguments);
    }.bind({ u: 0 });
}

XadillaX avatar Nov 20 '14 05:11 XadillaX

var once = function(fn) {
    if (typeof fn !== 'function') {
        alert('请传入待执行的函数');
        return;
    }
    var obj = {},
        flag = -1;
    return function() {
        for (var key in obj) {
            if (obj[key] === fn) {
                return console.log('no effect');
            }
        }
        obj[++flag] = fn;
        fn.apply(this, arguments);
    }
}

logOnce = once(console.log)
logOnce("foo") // -> 'foo'
logOnce("bar") // -> 'no effect'

soulcm avatar Nov 20 '14 05:11 soulcm

大神 @XadillaX 浏览器上不能运行怎么破?

Sanford2020 avatar Nov 20 '14 05:11 Sanford2020

@Jonavin -。 - 我不会前端,我的答案全是基于 node 的。

XadillaX avatar Nov 20 '14 05:11 XadillaX


function once(fn){
    var _fn = fn;
    return function() {
        var _f = _fn;
        return _fn ? ( _fn = null ,_f.apply(null,arguments)) : "no effect"; 
    }   
}

fireflyhoo avatar Nov 20 '14 06:11 fireflyhoo

var once = function(func) {
    if ( typeof func !== 'function' ) throw new Error('传入的参数必须是一个函数!');
    return function() {
        return this.n ? "no effect" : ( this.n = 1, func.apply(null, arguments) );
    }.bind( {n: 0} );
};

支持@XadillaX 的写法 :+1: 注:IE8及以下版本浏览器 不支持Function.prototype.bind()

Blueria avatar Nov 20 '14 09:11 Blueria

@Blueria 中写法如果那个函数本来就有个this.n呢?

hacke2 avatar Nov 20 '14 09:11 hacke2

@hacke2 又没关系,.bind 绑的是 function() {} 又不是 func。他俩又没关系。

XadillaX avatar Nov 20 '14 09:11 XadillaX

function once(fn) {
    var times = 1;

    return function () {
        --times || fn.apply(console, arguments);
    }
}

// 测试用例
logOnce = once(console.log);
logOnce('foo'); // foo
logOnce('bar'); // null

我的应该是最好理解的吧。 :D

think2011 avatar Nov 26 '14 02:11 think2011

@Jonavin 稍微研究了下,主要是apply的引用对象this(其实就是window),换成console就可以了。 之所以在node可以执行是因为console在node中是全局变量之一

VaJoy avatar Mar 07 '15 08:03 VaJoy