nunnly / everycode

Javascript 每日一练
116 stars 26 forks source link

2014年11月20日 #6

Open nunnly opened 10 years ago

nunnly commented 10 years ago

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

function once(fn){
    return fn
}

logOnce = once(console.log)
logOnce("foo") // -> "foo"
logOnce("bar") // -> no effect
jiehe commented 10 years ago

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") ;

XadillaX commented 10 years ago
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 commented 10 years ago

上一个无 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 commented 10 years ago

简化上面的做法:

function once(fn) {
    return function() {
        return this.u ? "no effect" : fn.apply((this.u = 1) && null, arguments);
    }.bind({ u: 0 });
}
soulcm commented 10 years ago
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'
Sanford2020 commented 10 years ago

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

XadillaX commented 10 years ago

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

fireflyhoo commented 10 years ago

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

Blueria commented 10 years ago
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()

hacke2 commented 10 years ago

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

XadillaX commented 10 years ago

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

think2011 commented 9 years ago
function once(fn) {
    var times = 1;

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

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

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

VaJoy commented 9 years ago

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