使用闭包创建我自己的console.log版本使用Javascript

时间:2016-02-25 21:23:29

标签: javascript function closures

我想创建自己的console.log版本,使用咖喱'功能,包括显示或不显示日志的可能性。 (灵感来自SecretsOfTheJavascriptNinja)

所以我使用闭包实现了这个功能:

Function.prototype.conditionalCurry = function() {
   var fn = this;
   var args = Array.prototype.slice.call(arguments);
   var show = args[0];
   args = args.slice(1, args.length);

   return function() {
      if (show) {
          return fn.apply(this, args.concat(   
                Array.prototype.slice.call(arguments)));
      }
      else return;
   };
};

当我使用终端中的节点测试代码时,它可以工作:

var newLog = console.log.conditionalCurry(true, 'Always visible|' );
newLog('log visible'); // gives on the console: Always visible| log visible

newLog = console.log.conditionalCurry(false, 'never visible|' );
newLog('log visible'); // gives nothing, it works!

但是当我在Chrome 48.0.2564.109上测试代码并在firefox 44.0.2中出现问题时,我认为两种情况都是一样的。

据我所知,不知何故,这个'这个'当我在终端中使用节点时传递给函数conditionalCurry,是一个匿名函数,但在浏览器的情况下,这个'显示为一个名为' log'的函数,我相信这会破坏代码。

任何想法如何在浏览器中实现此功能?

Fiddle

提前致谢!!!

使用Bergi的解决方案,现在可以使用:Fiddle

2 个答案:

答案 0 :(得分:1)

我会厌倦修改现有语言功能的原型,例如Function。看起来你真的想要这些日志工具的实例,所以你也可以定义那个实例并以“经典”的意义使用它。

例如,让我们创建一个名为“Logger”的“类”(仅使用语言不可知术语)。记录器实例可以配置为显示带前缀的消息,有条件地将消息发送到日志,还可以半传统方式使用日志。

function Logger(display,prefix){
  this.display = display == [][0] ? true : display;
  this.prefix = prefix;
}
Logger.prototype.log = function(){
  if(this.display){
    [].splice.apply(arguments,[0,0,this.prefix])
    console.log.apply(console,arguments);  
  }else{
    console.log(this.prefix);
  }
  return this;
};    
Logger.prototype.show = function(truthy){
  this.display = !!truthy;
  return this;
};
Logger.prototype.note = function(msg){
  this.prefix = msg;
  return this;
};

var newLog = new Logger(true,'always |');
newLog.log('show me');//always | show me

newLog.note('never show').show(false);
newLog.log('show me now');//never show

答案 1 :(得分:0)

这是执行上下文的问题。由于您将咖喱功能附加到功能原型','这个'关键字将引用您正在调用它的函数。在这种情况下,' log'在console.log中。

我不会修改原型,只需制作咖喱辅助功能:)

function curry(fn, ctx) {
  var slice = Array.prototype.slice.call;

  return function f() {
    var x = slice(arguments);
    // If we have enough arguments, call the function
    // You can get the arity with the 'length' property
    if (x.length >= fn.length) return fn.apply(ctx, x);
    // If not, collect more arguments
    return function () {
      var y = slice(arguments);
      return f.apply(null, x.concat(y));
    }
  }
}

// Trivial example
var curriedSum = curry(function(a, b, c) {
  return a + b + c;
});

// this now works
curriedSum(1, 2, 3);
curriedSum(1)(2, 3);
curriedsum(1)(2)(3);



// for your use case
var curriedLog = curry(function(show, prefix, msg) {
  if (! show) return;

  return console.log(prefix + msg);
});

// Use like so
var neverLogs = curriedLog(false);
neverLog('Some Prefix|', 'some message') // never logs

var logWithPrefix = curriedLog(true, 'This is my prefix|');
logWithPrefix('wassup') // logs   'this is my prefix| wassup'

如果你需要强迫这个'将关键字作为特定对象,将该对象作为第二个参数传递。

curry(fn, context);