如何在不影响性能的情况下将详细日志logging代码添加到函数中?

对于我正在编写的某个课程,performance很重要。

我想过调用一个这样的函数:

debug('This is a debug message, only visible when debugging is on'); 

内容会是这样的

 function debug(message) { if (DEBUG) console.log(message); } 

所以我想知道:如果DEBUGvariables永远不会改变,V8是否足以将其标记为“死代码”?

编辑:我更担心节点比在浏览器的性能,所以在缩小的时候删除代码是不够的。

编辑2:我提出了一个JSPerf基准testing的解决scheme,他们是非常令人惊讶的: http : //jsperf.com/verbose-debug-loggin-conditionals-functions-and-no-ops/3

有几个解决scheme可用(旁边的Petah的 …):

  1. 使用UglifyJS2条件编译 :

您可以使用–define(-d)开关来声明UglifyJS将假定为常量的全局variables(除非在作用域中定义)。 例如,如果你传递–define DEBUG = false,那么再加上死代码的移除,UglifyJS会从输出中丢弃以下内容:

 if (DEBUG) { console.log("debug stuff"); } 

UglifyJS会警告总是出现错误的情况,并会丢弃无法访问的代码; 现在没有选项只能closures这个特定的警告,你可以通过warnings = false来closures所有的警告。

另一种方法是将你的全局variables声明为一个单独的文件,并将其包含到构build中。 例如你可以使用下面的build / defines.js文件:

 const DEBUG = false; const PRODUCTION = true; // etc. and build your code like this: 

uglifyjs build /developers.js js / foo.js js / bar.js … -c UglifyJS会注意到这些常量,因为它们不能被修改,所以它会评估对它们的引用,并像往常一样放弃无法访问的代码。 这种方法可能的缺点是构build将包含常量声明。

  1. 使用包装函数。

比如你有这个方法:

 exports.complicatedMethod = function (arg1, arg2, arg3) { stuff... }; 

通过将logging包装到logging器函数中来添加logging:

 function logger(fn) { if (!DEBUG) { return fn; } return function () { console.log(fn.name, arguments); // You can also use `fn.toString()` to get the argument names. fn.apply(this, arguments); }; } exports.complicatedMethod = logger(function (arg1, arg2, arg3) { stuff... }); 

这种方式唯一的performance将是在启动时间。 你也可以使用上面的包装函数使用AOP方法:

 exports.complicatedMethod = function (arg1, arg2, arg3) { stuff... }; if (DEBUG) { for (var name in exports) { exports[name] = logger(exports[name]); } } 

你可以通过给函数添加属性来传递信息给logging器:

 exports.complicatedMethod.description = 'This function only shows how tired i was when I was writing it and nothing else!'; 

你可以看看这个问题 ,其中有人创build了代码,recursion地为对象中的函数创build一个logging器。 也检查我的这个答案 。

  1. 使用C预处理器 。

你可以做这样的事情:

 #if DEBUG console.log("trace message"); #endif 

或者类似的东西

 #if DEBUG #define DEBUG_LOG(x) console.log(x); #else #define DEBUG_LOG(x) //console.log(x); #endif 

那么你可以在你的代码中做到这一点

 DEBUG_LOG('put a random message her to confuse sys admins!') 

或者你用它的npm warapper:laudanumscript

  1. 创build一个sweetjsmacros 。

我还没有findsweetjs的条件编译,但我相信它不会太难实现它。 最后的语法应该是(或应该是!)类似于CPP。

我使用的评论,当一个文件被缩小被删除,如:

 function name(arg) { // <debug> if (!arg) { throw new Error("arg must be defined"); } // </debug> ... code goes here } 

例如: https : //github.com/PANmedia/raptor-editor/blob/master/src/raptor-widget.js#L29-L33

我的(自定义)生成脚本做上述https://github.com/PANmedia/raptor-build/blob/master/build/raptor-builder.js#L305-L313

您可以使用支持以下function的logging器库:

  1. logging级别
  2. 后期绑定function

例如: https : //github.com/duongchienthang/js-logger

Interesting Posts