告诉写 JavaScript 的人应该使用浏览器的调试器去调试代码,这看来很不错,并且肯定有其适用的时间和场合。但是大多数时候你仅仅只想查看一段特定的代码是否执行或者一个变量的值是什么,而不是迷失在 RxJS 代码库或者一个 Promise 库的深处。
然而,尽管 console.log 有其适用的场合,大多数人仍然没有意识到 console 本身除了基础 log 还有许多选择。合理使用这些方法能让调试更简单、更快速,并且更加直观。
console.log()很多人不知道经典的 console.log 其实有着丰富的函数特性。尽管大多数人只使用 console.log(object) 这种语法,但你仍然能写 console.log(object, otherObject, string) 并且它会将所有东西都整齐的打印出来。有时候确实很方便。
不止那些,这儿还有另一种格式:console.log(msg, values)。这个执行方式和 C 或者 PHP 的 sprintf 很相似。
1 | console.log('I like %s but I do not like %s.', 'Skittles', 'pus'); |
1 | > I like Skittles but I do not like pus. |
%o
%s
%d
%c
1 | console.log('I am a %cbutton', 'color: white; background-color: orange; padding: 2px 5px; border-radius: 2px'); |
console.dir()
1 | let element = document.getElementById('2x-container'); |
console.warn()可能是 log() 最直接明显的替换,你可以用相同的方式使用 console.warn()。唯一的区别在于输出是一抹黄色。确切的说,输出是一个 warn 级别而不是一个 info 级别的信息,因此浏览器的处理稍稍有些不同。在一堆杂乱的输出中高亮你的输出是很有效果的。
不过,这还有一个更大的优点。因为输出是一个 warn 级别而不是一个 info 级别,你可以将所有的 console.log 过滤掉只留下 console.warn。这有时在那些不停输出一堆无用和无意义的东西到浏览器的随意的应用程序中是非常有用。屏蔽干扰能更容易的看到你自己的输出。
console.table()
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | const transactions = [{ id: "7cb1-e041b126-f3b8", seller: "WAL0412", buyer: "WAL3023", price: 203450, time: 1539688433},{ id: "1d4c-31f8f14b-1571", seller: "WAL0452", buyer: "WAL3023", price: 348299, time: 1539688433},{ id: "b12c-b3adf58f-809f", seller: "WAL0012", buyer: "WAL2025", price: 59240, time: 1539688433}]; |
1 | ▶ (3) [{…}, {…}, {…}] |
值得一提的是在最右一列头部的右上角有个箭头可以颠倒次序。点击了它,会排序整个列。非常方便的找出一列的最大或者最小值,或者只是得到不同的数据展示形式。这个功能特性并没有做什么,只是对列的展示。但总会是有用的。
console.table() 只有处理最多1000行的数据的能力,所以它可能并不适用于所有的数据集合。
console.assert()一个经常被忽视的实用的函数,assert() 在第一个参数是 falsey 时和 log() 一样。当第一个参数为真值时也什么都不做。
这个在你需要循环(或者不同的函数调用)并且只有一个要显示特殊的行为的场景下特别有用。本质上和这个是一样的。
1 2 3 | if (object.whatever === 'value') { console.log(object);} |
1 | console.assert(tx.timestamp, tx); |
1 | console.assert(tx.buyer !== 'WAL0412', tx); |
我们想做的就是这样。在那种情况下,所有不是 WAL0412 号顾客的事务都为真值,只留下那些符合的事务。或者,也不完全是。
诸如此类,console.assert() 并不是一直都很管用。但是在特定的场景下会是最优雅的的解决方法。
console.count()另外一个合适的用法是,将console作为一个计数器使用。
01 02 03 04 05 06 07 08 09 10 11 | for(let i = 0; i < 10000; i++) { if(i % 2) { console.count('odds'); } if(!(i % 5)) { console.count('multiplesOfFive'); } if(isPrime(i)) { console.count('prime'); }} |
01 02 03 04 05 06 07 08 09 10 11 | odds: 1odds: 2prime: 1odds: 3multiplesOfFive: 1prime: 2odds: 4prime: 3odds: 5multiplesOfFive: 2... |
以及剩下的。在你只想列出索引,或者想保留一次(或多次)计数的情况下非常有用。
你也能像那样使用 console.count(),不需要参数。使用 default 调用。
这还有关联函数 console.countReset(),如果你希望重置计数器可以使用它。
console.trace()这在简单的数据中演示更加困难。在你试图找出有问题的内部类或者库的调用这一块是它最擅长。
举个例子,这儿可能有 12 个不同的组件正在调用一个服务,但是其中一个没有正确配置依赖。
01 02 03 04 05 06 07 08 09 10 11 | export default class CupcakeService { constructor(dataLib) { this.dataLib = dataLib; if(typeof dataLib !== 'object') { console.log(dataLib); console.trace(); } } ...} |
这里单独使用 console.log() 我们只能知道执行了哪一个基础库,并不知道执行的具体位置。但是,堆栈轨迹会清楚的告诉我们问题在于 Dashboard.js,我们从中发现 new CupcakeService(false) 是造成出错的罪魁祸首。
console.time()console.time() 是专门用于监测操作的时间开销的函数,也是监测 JavaScript 细微时间的更好的方式。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | function slowFunction(number) { var functionTimerStart = new Date().getTime(); // something slow or complex with the numbers. // Factorials, or whatever. var functionTime = new Date().getTime() - functionTimerStart; console.log(`Function time: ${ functionTime }`);}var start = new Date().getTime();for (i = 0; i < 100000; ++i) { slowFunction(i);}var time = new Date().getTime() - start;console.log(`Execution time: ${ time }`); |
01 02 03 04 05 06 07 08 09 10 11 12 | const slowFunction = number => { console.time('slowFunction'); // something slow or complex with the numbers. // Factorials, or whatever. console.timeEnd('slowFunction');}console.time();for (i = 0; i < 100000; ++i) { slowFunction(i);}console.timeEnd(); |