前言 前几天在看青柠起始页 的时候偶然间看到它的控制台居然可以这样 👊
于是就萌生了学一波 console 方法的念头,今天正好有时间就来把这几天的学习成果记录一下 😶
console 的基本用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 console .log ("最常见用法\n换行" );console .error ("输出错误信息 会以红色显示" );console .warn ("打印警告信息 会以黄色显示" );console .info ("打印一般信息" );console .assert (false , "判断为false才显示的信息" );console .table ([["Anzhiyu" , "Chen" ], ["好" ]]);function fn ( ) { console .trace (); } function fn1 ( ) { fn (); } function fn2 ( ) { fn1 (); } fn2 ();console .log ("%d + %d = %d" , 1 , 2 , 3 );console .log ("%o" , document .body );console .log ("%O" , document .body );console .log ("123 %c 456" , "font-size:36px;color:red;" );console .log ("123 %c 4 https://anheyu.com 56 %c 789" , "font-size:20px;color:#3b70fc;" , "font-size:12px;color:#000" );console .log ( "%c " , 'background-image:url("https://cdn.jsdelivr.net/gh/waterchen520/cdn2@latest/anheyu.com.jpg");background-size:120% 120%;background-repeat:no-repeat;background-position:center center;line-height:60px;padding:30px 120px;' ); console .time ();for (var i = 0 ; i < 100000 ; i++) { var j = i * i; } console .timeEnd ();var fn_ = function ( ) { console .count ("hello world" ); }; for (var i = 0 ; i < 5 ; i++) { fn_ (); } console .group ("分组1" );console .log ("语文" );console .log ("数学" );console .group ("其他科目" );console .log ("化学" );console .log ("地理" );console .log ("历史" );console .groupEnd ("其他科目" );
展开上面代码运行可以得到
注意以上某些方法某些浏览器IE:没错就是我 不支持
console 详解 让我们来看看谷歌浏览器提供的 console 方法的 API https://developer.chrome.com/docs/devtools/console/
我们来重写 console,发现它里面有很多方法
console.assert(expression, object) 在被评估的表达式为 false
时向控制台写入一个错误。
1 2 3 4 function greaterThan (a, b ) { console .assert (a > b, { message : "a is not greater than b" , a : a, b : b }); } greaterThan (5 , 6 );
console.clear() 清除控制台。
如果已启用 Preserve log 复选框,console.clear()
将停用。 不过,在控制台处于聚焦状态时,按 clear console 按钮或者输入 Ctrl+L 快捷键仍然有效。
console.count(label) 写入在同一行使用相同标签调用 count()
的次数。
1 2 3 function login(name) { console.count(name + ' logged in'); }
console.debug(object [, object, …]) 与 console.log()
作用相同。
console.dir(object) 输出以 JavaScript 形式表示的指定对象。如果正在记录的对象是 HTML 元素,将输出其以 DOM 形式表示的属性,如下所示:
1 console.dir(document.body);
比 console.log 更加详细
console.dirxml(object) 如果可以,输出 object 子级元素的 XML 表示形式,否则输出其 JavaScript 表示形式。 在 HTML 和 XML 元素上调用 console.dirxml()
等同于调用 console.log()
。
1 console .dirxml (document );
console.error(object [, object, …]) 输出一条类似于 console.log()
的消息,将消息设置成错误样式,并在调用此方法的地方包含一个堆叠追踪。
1 console.error('error: name is undefined');
console.group(object[, object, …]) 启动一个带有可选标题的新日志组。以可视化方式将在 console.group()
后、console.groupEnd()
前发生的所有控制台输出组合在一起。
1 2 3 4 5 6 7 8 9 function name (obj ) { console .group ("name" ); console .log ("first: " , obj.first ); console .log ("middle: " , obj.middle ); console .log ("last: " , obj.last ); console .groupEnd (); } name ({ first : "Wile" , middle : "E" , last : "Coyote" });
您还可以嵌套组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function name (obj ) { console .group ("name" ); console .log ("first: " , obj.first ); console .log ("middle: " , obj.middle ); console .log ("last: " , obj.last ); console .groupEnd (); } function doStuff ( ) { console .group ("doStuff()" ); name ({ first : "Wile" , middle : "E" , last : "coyote" }); console .groupEnd (); } doStuff ();
console.groupCollapsed(object[, object, …]) 创建一个初始处于折叠状态而不是打开状态的新日志组。
1 2 3 console .groupCollapsed ("status" );console .log ("peekaboo, you can't see me" );console .groupEnd ();
console.groupEnd() 关闭日志组。相关示例请参阅 console.group
。
console.info(object [, object, …]) 输出一条类似 console.log()
的消息,但同时在输出旁显示一个图标(带白色“i”的蓝色圆圈)。
console.log(object [, object, …]) 在控制台中显示一条消息。将一个或多个对象传递到此方法。每个对象都会进行评估并级联到一个由空格分隔的字符串中。
1 console .log ("Hello, Logs!" );
格式说明符 您传递的第一个对象可以包含一个或多个格式说明符。格式说明符由百分号 (%) 与紧跟其后面的一个字母组成,字母指示要应用的格式。
console.profile([label]) 启动一个带有可选标签的 JavaScript CPU 配置文件。要完成配置文件,请调用 console.profileEnd()
。 每一个配置文件都会添加到 Profiles 面板中。
1 2 3 4 5 function processPixels ( ) { console .profile ("processPixels()" ); console .profileEnd (); }
console.profileEnd() 停止当前的 JavaScript CPU 分析会话(如果正在进行此会话),并将报告输出到 Profiles 面板中。
console.time(label) 启动一个具有关联标签的新计时器。使用相同标签调用 console.timeEnd() 时,定时器将停止,经过的时间将显示在控制台中。计时器值精确到亚毫秒。传递到 time()
和 timeEnd()
的字符串必须匹配,否则计时器不会结束。
1 2 3 4 5 6 console .time ("Array initialize" );var array = new Array (1000000 );for (var i = array.length - 1 ; i >= 0 ; i--) { array[i] = new Object (); } console .timeEnd ("Array initialize" );
console.timeEnd(label) 停止当前的计时器(如果正在运行一个计时器),并将计时器标签和经过的时间输出到控制台。
console.timeStamp([label]) 在录制会话期间向 Timeline 添加一个事件。
1 console .timeStamp ("check out this custom timestamp thanks to console.timeStamp()!" );
console.trace(object) 从调用此方法的位置输出一个堆叠追踪。
console.warn(object [, object, …]) 输出一条类似 console.log()
的消息,但同时在记录的消息旁显示一个黄色警告图标。
1 console .warn ("user limit reached!" );
重写简单的 console 方法 我们常用的有 console.log、console.info、console.group、console.warn、console.error、console.profile、console.time,现在我们来试着重写 console.log、console.info、console.group、console.warn、console.error 这几个常用的,其他的类似但比较复杂。
第一步,搭一个结构,覆盖浏览器(chrome\ie)提供的 console 功能,这样直接引用此 JS 文件即可保证浏览器(主要是 IE)中不出错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var console = { assert : function ( ) {}, clear : function ( ) {}, count : function ( ) {}, debug : function ( ) {}, dir : function ( ) {}, dirxml : function ( ) {}, error : function ( ) {}, exception : function ( ) {}, group : function (name ) {}, groupCollapsed : function ( ) {}, groupEnd : function ( ) {}, info : function ( ) {}, log : function ( ) {}, memoryProfile : function ( ) {}, memoryProfileEnd : function ( ) {}, profile : function ( ) {}, profileEnd : function ( ) {}, table : function ( ) {}, time : function ( ) {}, timeEnd : function ( ) {}, timeStamp : function ( ) {}, trace : function ( ) {}, warn : function ( ) {}, };
第二步,实现 console.log 方法。在所实现的几个方法中这个是最复杂的。
从 chrome 的 API 中我们可以看到,console.log 不仅仅可以输出信息,还提供了类似 string.Format 的功能,原文地址:https://developer.chrome.com/docs/devtools/console/api/
Here is the complete set of patterns that you may use for string substitution:
Pattern Type %s String %d, %i Integer (numeric formatting is not yet supported) %f Floating point number (numeric formatting is not yet supported) %o Object hyperlink %c Style formatting
其中的%c 比较特殊,是给输出添加样式的,比如我们在 Chrome 中这样写:
1 console .log ("%cTest output" , "color:white; background-color:blue" );
运行后的结果是这样的:
这里%c 也可以跟 %s、%d 等混用。
所以,在代码中我直接用 replace 进行替换,由于 JS 中的 replace 默认只替换第一个匹配项,这里刚好,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 var args = Array .prototype .slice .call (arguments );if (args.length > 1 ) { var i = 1 , hasstyle = false ; if (args[0 ].indexOf ("%c" ) == 0 ) { args[0 ] = args[0 ].replace (/%c/ , "" ); i = 2 ; hasstyle = true ; } for (; i < args.length ; i++) { if (/%s|%d|%i|%o/ .test (args[0 ])) { args[0 ] = args[0 ].replace (/%s|%d|%i|%o/ , args[i]); } else { break ; } } if (i < args.length ) { args[0 ] = args[0 ] + " " + args.slice (i).join (" " ); } if (hasstyle) { consoleHelper.showlog (args[0 ], args[1 ]); } else { consoleHelper.showlog (args[0 ]); } } else if (args.length == 1 ) { if (arguments [0 ] instanceof Array ) { consoleHelper.showlog ("[" + args[0 ] + "]" ); } else if (arguments [0 ] instanceof Function ) { consoleHelper.showlog (args[0 ], null , "console_log_function" ); } else { consoleHelper.showlog (args[0 ]); } } else { consoleHelper.showlog ("" ); }
由于 console.log 可以接受多个参数,且个数不确定,所以这里直接没有写形参。对于%c 虽然 Chrome 中写在中间也是有效的,这里为了简单直接只对写在开头的有效。代码中先把参数转换为数组,然后对数组进行分情况处理。
当参数个数大于 1 时,对后面的参数用 replace 进行替换,然后把剩下的参数连接(join)起来进行输出。
当参数个数为 1 时,还要分两种情况,一是数组,二是方法。对于数组,按 Chrome 中的格式,在两端加中括号,对于函数,把字的颜色变为绿色
当参数个数为 0 时,直接输出空字符串
后面的 consoleHelper.showlog 是为了输出方便另外写的一个方法,在这个方法中把各种调试信息的结果显示在页面上的一个 div(如果存在)中。
其他几个方法的思路跟这个差不多,只是样式不同,功能比这个简单,直接把参数连接起来输出即可。
整个 console 类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 var console = { assert : function ( ) {}, clear : function ( ) {}, count : function ( ) {}, debug : function ( ) {}, dir : function ( ) {}, dirxml : function ( ) {}, error : function ( ) { var args = Array .prototype .slice .call (arguments ); consoleHelper.showerror (args.join (" " )); }, exception : function ( ) {}, group : function (name ) { consoleHelper.showgroup (name); }, groupCollapsed : function ( ) {}, groupEnd : function ( ) {}, info : function ( ) { var args = Array .prototype .slice .call (arguments ); if (args.length == 1 ) { if (arguments [0 ] instanceof Array ) { consoleHelper.showinfo ("[" + args[0 ] + "]" ); } else if (arguments [0 ] instanceof Function ) { consoleHelper.showinfo (args[0 ], "console_log_function" ); } else { consoleHelper.showinfo (args[0 ]); } } else { consoleHelper.showinfo (args.join (" " )); } }, log : function ( ) { var args = Array .prototype .slice .call (arguments ); if (args.length > 1 ) { var i = 1 , hasstyle = false ; if (args[0 ].indexOf ("%c" ) == 0 ) { args[0 ] = args[0 ].replace (/%c/ , "" ); i = 2 ; hasstyle = true ; } for (; i < args.length ; i++) { if (/%s|%d|%i|%o/ .test (args[0 ])) { args[0 ] = args[0 ].replace (/%s|%d|%i|%o/ , args[i]); } else { break ; } } if (i < args.length ) { args[0 ] = args[0 ] + " " + args.slice (i).join (" " ); } if (hasstyle) { consoleHelper.showlog (args[0 ], args[1 ]); } else { consoleHelper.showlog (args[0 ]); } } else if (args.length == 1 ) { if (arguments [0 ] instanceof Array ) { consoleHelper.showlog ("[" + args[0 ] + "]" ); } else if (arguments [0 ] instanceof Function ) { consoleHelper.showlog (args[0 ], null , "console_log_function" ); } else { consoleHelper.showlog (args[0 ]); } } else { consoleHelper.showlog ("" ); } }, memoryProfile : function ( ) {}, memoryProfileEnd : function ( ) {}, profile : function ( ) {}, profileEnd : function ( ) {}, table : function ( ) {}, time : function ( ) {}, timeEnd : function ( ) {}, timeStamp : function ( ) {}, trace : function ( ) {}, warn : function ( ) { var args = Array .prototype .slice .call (arguments ); if (args.length == 1 ) { if (arguments [0 ] instanceof Array ) { consoleHelper.showwarn ("[" + args[0 ] + "]" ); } else if (arguments [0 ] instanceof Function ) { consoleHelper.showwarn (args[0 ], "console_log_function" ); } else { consoleHelper.showwarn (args[0 ]); } } else { consoleHelper.showwarn (args.join (" " )); } }, };
consoleHelper 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 var consoleHelper = { showlog : function (val, style, cla ) { if (cla) { cla = "console_log " + cla; } else { cla = "console_log" ; } this .show (val, style, cla); }, showinfo : function (val, cla ) { if (cla) { cla = "console_info " + cla; } else { cla = "console_info" ; } this .show (val, null , cla); }, showwarn : function (val, cla ) { if (cla) { cla = "console_warn " + cla; } else { cla = "console_warn" ; } this .show (val, null , cla); }, showerror : function (val ) { this .show (val, null , "console_error" ); }, showgroup : function (val ) { if (!val) { val = "" ; } this .show (val + ":" , null , "console_group" ); }, show : function (val, style, cla ) { if (document .getElementById ("showconsole" )) { var div = document .createElement ("div" ); if (div.setAttribute ) { if (style) { div.setAttribute ("style" , style); } } else { if (style) { div = document .createElement ("<div style=" + style + ">" ); } } if (cla) { div.className = cla; } var oText = document .createTextNode (val); div.appendChild (oText); document .getElementById ("showconsole" ).appendChild (div); } }, };
注:如果想在页面中看到调试信息,直接在页面上添加一个id 为 showconsole 的隐藏的div即可。
样式(尽量跟 Chrome 保持一致):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 .console_log { border : 1px solid #ccc ; color : #333 ; padding : 0px 5px ; min-height : 24px ; line-height : 24px ; margin-bottom : -1px ; } .console_info { border : 1px solid #ccc ; color : #333 ; padding : 0px 5px ; min-height : 24px ; line-height : 24px ; margin-bottom : -1px ; background : url ("这里是info方法的小图标" ) no-repeat scroll 0 1px #ebf5ff ; padding-left : 30px ; } .console_warn { border : 1px solid #ccc ; color : #333 ; padding : 0px 5px ; min-height : 24px ; line-height : 24px ; margin-bottom : -1px ; background : url ("这里是warn方法的小图标" ) no-repeat scroll 0 1px #ffffc8 ; padding-left : 30px ; } .console_error { border : 1px solid #ccc ; color : #ff0000 ; padding : 0px 5px ; min-height : 24px ; line-height : 24px ; margin-bottom : -1px ; background : url ("这里是error方法的小图标" ) no-repeat scroll 0 1px #ffebeb ; padding-left : 30px ; } .console_group { margin-top : 20px ; font-size : 16px ; font-weight : bolder; } .console_log_function { color : green; }
这里为了演示方便,三个小图标直接预留了位置,大家用时可以换成图片地址。
代码实现案例 如果只需要一个简单的,类似我博客里的这种,你只需要写一个 js
下面是本博客控制台的 js 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 var now1 = new Date ();function createtime1 ( ) { var grt = new Date ("04/01/2021 00:00:00" ); now1.setTime (now1.getTime () + 250 ); var days = (now1 - grt) / 1000 / 60 / 60 / 24 ; var dnum = Math .floor (days); var ascll = [ `欢迎来到Anzhiyu\`Blog!` , `生活明朗, 万物可爱` , ` ██╗ ██╗██╗ ██████╗ ██╗ ███████╗████████╗ ██║ ██║██║██╔═══██╗██║ ██╔════╝╚══██╔══╝ ██║ ██║██║██║ ██║██║ █████╗ ██║ ╚██╗ ██╔╝██║██║ ██║██║ ██╔══╝ ██║ ╚████╔╝ ██║╚██████╔╝███████╗███████╗ ██║ ╚═══╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ` , "Anzhiyu`Blog 已上线" , dnum, "天" , "©2021 By Anzhiyu" , ]; setTimeout ( console .log .bind ( console , `\n%c${ascll[0 ]} %c ${ascll[1 ]} %c ${ascll[2 ]} %c${ascll[3 ]} %c ${ascll[4 ]} %c ${ascll[5 ]} \n\n%c ${ascll[6 ]} \n` , "color:#3b70fc" , "" , "color:#3b70fc" , "color:#3b70fc" , "" , "color:#3b70fc" , "" ) ); } createtime1 ();function createtime2 ( ) { var ascll2 = [`NCC2-036` , `调用前置摄像头拍照成功,识别为【小笨蛋】.` , `Photo captured: ` , ` ` ]; setTimeout ( console .log .bind ( console , `%c ${ascll2[0 ]} %c ${ascll2[1 ]} %c \n${ascll2[2 ]} %c\n${ascll2[3 ]} \n` , "color:white; background-color:#4fd953" , "" , "" , 'background:url("https://unpkg.zhimg.com/anzhiyu-assets@latest/image/common/tinggge.gif") no-repeat;font-size:450%' ) ); setTimeout (console .log .bind (console , "%c WELCOME %c 你好,小笨蛋." , "color:white; background-color:#4f90d9" , "" )); setTimeout ( console .warn .bind ( console , "%c ⚡ Powered by Anzhiyu %c 你正在访问 Anzhiyu 的博客." , "color:white; background-color:#f0ad4e" , "" ) ); setTimeout (console .log .bind (console , "%c W23-12 %c 你已打开控制台." , "color:white; background-color:#4f90d9" , "" )); setTimeout ( console .warn .bind (console , "%c S013-782 %c 你现在正处于监控中." , "color:white; background-color:#d9534f" , "" ) ); } createtime2 ();console .log = function ( ) {};
写下这篇博客的时候 📌,已经忘记参考地址是哪里了,算是一个汇总吧,参考地址百度
啦啦啦~
我一直想从你的窗子里看月亮。💡~