JavaScript中的console

前言

之前调试JS代码用的一直是console.log(),偶然间了解到console 对象拥有多种方法可以更好的呈现信息。调试代码时可根据不同情况选择不同的console,从而给代码调试带来方便。根据常用程度,列出以下几种 console 对象的方法:

  • console.log()、console.debug()、console.info()、console.warn() 与 console.error()
  • console.table()
  • console.time() 与 console.timeEnd()
  • console.assert()
  • console.count()
  • console.group、console.groupEnd() 与 console.groupCollapsed()
  • console.dir()

以下示例的运行环境是VSCode中的Nodejs和谷歌浏览器。

console对象

console.log()

console.log是最常用的打印信息方法,它可以接受多个参数,逗号分隔。它会自动在每次输出的结尾,添加换行符。没有返回值回会返回undefined

如果第一个参数是格式字符串(使用了格式占位符),console.log方法将依次用后面的参数替换占位符,然后再进行输出。

console.log('hello %s', 'world');
// hello world
console.log("%d年%d月%d日", 2022, 05, 23)
// 2022年5月23日

占位符格式如下表:

模式类型
%s字符串
%d,%i整数
%f浮点数
%o对象超链接
%cCSS格式化样式

console.log()方法和console.debug()console.info()console.warn()console.error()几乎完全一样,唯一不同的是现实中浏览器的表现形式了。(在nodejs运行环境中表现形式相同)
在这里插入图片描述
注意:IE不支持debug()方法

console.table()

console.table()方法可以将传入的对象或数组这些复合数据以表格形式输出。

const people = {
    "person1": {"name": "zhangsan", "age": "20"}, 
    "person2": {"name": "lisi", "age": "21"}, 
    "person3": {"name": "wangwu", "age": "22"}
};
console.log(people);

console.table(people);

在这里插入图片描述
所以从上面两种输出我们可以看出,当输出类似于这种两层嵌套的对象时,我们可以选择 console.table() 以表格的形式输出。当然,嵌套三层及以上的也会以表格形式输出,但限于表格只能显示二维信息的特点,其会在嵌套三层或以上的地方会显示 “Object” 字符串。

console.time() 与 console.timeEnd()

console.time(),console.timeEnd()方法计算一个操作的执行的时间console.time()是开始,console.timeEnd()是结束。可以传一个参数,参数为计时器的名称。

console.time('计时器');
    for (var i = 0; i < 100; i++) {
        for (var j = 0; j < 100; j++) {}
   }
console.timeEnd('计时器');
// 计时器: 0.196ms

console.time('wait');
setTimeout(()=>{
	console.timeEnd('wait');
},1000);
// wait: 1008.538ms

console.assert()

如果第一个参数的值为假值或省略,则 console.assert() 写入一条消息,将会在控制台上抛出一个异常并将第二个参数作为异常描述输出。 它只写入一条消息,不会影响执行。 输出始终以 “Assertion failed” 开头。
如果第一个参数的值为真值,则什么也不会发生。

console.assert(true, 'does nothing');

console.assert(false, 'Whoops %s work', 'didn\'t');
// Assertion failed: Whoops didn't work

console.assert();
// Assertion failed

也可以直接进行判断,类似于单元测试中的断言,当表达式为 false 时,输出错误信息。示例如下:

const arr = [1, 2, 3];
console.assert(arr.length === 4);
// Assertion failed

注意:Node.js 中的 console.assert() 方法与在浏览器中的 console.assert() 方法的实现是不一样的。

具体地说,在浏览器中,用非真的断言调用console.assert()会导致 message 被打印到控制台但不会中断后续代码的执行。 而在 Node.js 中,非真的断言会导致抛出AssertionError

可以通过扩展 Node.js 的 console 并重写console.assert()方法来实现与浏览器中类似的功能。

例子,创建一个简单的模块,并扩展与重写了 Node.js 中 console 的默认行为。

'use strict';

// 用一个新的不带补丁的 assert 实现来创建一个简单的 console 扩展。
const myConsole = Object.create(console, {
  assert: {
    value: function assert(assertion, message, ...args) {
      try {
        console.assert(assertion, message, ...args);
      } catch (err) {
        console.error(err.stack);
      }
    },
    configurable: true,
    enumerable: true,
    writable: true,
  },
});

module.exports = myConsole;

然后可以用来直接替换内置的 console:

const console = require('./myConsole');
console.assert(false, '会打印这个消息,但不会抛出错误');
console.log('这个也会打印');

console.count()与console.countReset()

console.count()方法用于计数,输出它被调用了多少次。

for (var i = 0; i < 5; i++) { 
    console.count('count'); 
}
// count: 1
// count: 2
// count: 3
// count: 4
// count: 5

console.count()参数默认值为'default'

console.count()
// default: 1
console.count('default')
// default: 2
console.count()
// default: 3

console.countReset()用于重置特定于console.count()的内部计数器。

console.count('abc');
// abc: 1
console.countReset('abc');
console.count('abc');
// abc: 1

console.group()、 console.groupEnd() 与 console.groupCollapsed()

一般的console.log()方法的输出没有层级关系,在需要一些显示层级关系的输出中显得苍白无力,使用console.group()可以达到我们的目的。示例代码如下:

console.group("1");
console.log("1-1");
console.log("1-2");
console.log("1-3");
console.groupEnd();
console.group("2");
console.log("2-1");
console.log("2-2");
console.log("2-3");
console.groupEnd();
// 1
//   1-1
//   1-2
//   1-3
// 2
//   2-1
//   2-2
//   2-3

console.group()console.groupCollapsed()这两个方法用法都是一样的。唯一区别就是在浏览器中console.group()是默认展开的,而console.groupCollapsed()默认是收起的,在node.js中显示无差别。

console.group('第一层');
    console.groupCollapsed('第二层');

        console.log('error');
        console.error('error');
        console.warn('error');

    console.groupEnd(); 
console.groupEnd(); 

浏览器显示结果:
在这里插入图片描述
nodejs显示结果:
在这里插入图片描述

console.dir()

console.dir()方法用来对一个对象进行检查,并以易于阅读和打印的格式显示。

var obj1 = {
    name: 'zhangsan',
    age: '18',
    type: {
    	"A" : "a",
    	"B" : "b",
    	"C" : "c"
    }
  };
  console.dir(obj1);

  var arr = [1,2,3]
  console.dir(arr)

  var s = 'abcde'
  console.dir(s)

  var n = 123
  console.dir(n)

在谷歌浏览器运行结果为:
在这里插入图片描述
点击展开显示为:
在这里插入图片描述
换成console.log()方法则为:
在这里插入图片描述
显示内容有一定的差别。
在nodejs环境中显示内容没有差别:
在这里插入图片描述
但是在对象嵌套层级过多的情况下,在第2级之后的嵌套对象会被扁平化,如下:

var obj = {
    name: 'joe',
    age: 35,
    person1: {
        name: 'Tony',
        age: 50,
        person2: {
            name: 'Albert',
            age: 21,
            person3: {
                name: 'Peter',
                age: 23,
            },
        },
    },
};

console.dir(obj)
// {
//     name: 'joe',
//     age: 35,
//     person1: {
//       name: 'Tony',
//       age: 50,
//       person2: { name: 'Albert', age: 21, person3: [Object] }
//     }
//   }

console.log(obj)
// {
//     name: 'joe',
//     age: 35,
//     person1: {
//       name: 'Tony',
//       age: 50,
//       person2: { name: 'Albert', age: 21, person3: [Object] }
//     }
//   }

可以通过以下方式解决:

// 'depth'告诉util.inspect()格式化对象时递归的次数,默认为2
console.dir(obj, {
  depth: 10
});

// ...或者传递' null '来无限递归
console.dir(obj, {
  depth: null
});

// {
//     name: 'joe',
//         age: 35,
//             person1: {
//         name: 'Tony',
//             age: 50,
//                 person2: { name: 'Albert', age: 21, person3: { name: 'Peter', age: 23 } }
//     }
// }

此外在 Chrome 中打印 DOM 元素时,两个方法输出的结果也大不一样。console.log()会将 DOM 元素以 HTML 的形式输出,而console.dir()则会以 JSON 对象的形式输出。
在这里插入图片描述
在这里插入图片描述

在Node.js中,同样的情况也会发生。
当我们将一些东西记录到控制台时,我们没有这样的特权,因为如果手动运行Node.js程序,它会将对象输出到shell,或者输出到日志文件。你得到对象的字符串表示。
现在,一切都很好,直到一定程度的嵌套。在两层嵌套之后,Node.js放弃并打印[Object]作为一个占位符:

const obj = {
  name: 'joe',
  age: 35,
  person1: {
    name: 'Tony',
    age: 50,
    person2: {
      name: 'Albert',
      age: 21,
      person3: {
        name: 'Peter',
        age: 23,
      },
    },
  },
};
console.log(obj);

拓展

如何在Node.js中log一个对象

当你在浏览器中运行的JavaScript程序中输入console .log()时,会在浏览器控制台中创建一个不错的条目,一旦你点击箭头,日志就展开了,你可以清楚地看到对象属性。
在Node.js中,同样的情况也会发生。
当我们将一些东西记录到控制台时,我们没有这样的特权,因为如果手动运行Node.js程序,它会将对象输出到shell,或者输出到日志文件。你得到对象的字符串表示。
现在,一切都很好,直到一定程度的嵌套。在两层嵌套之后,Node.js放弃并打印[Object]作为一个占位符。
如何打印整个物体?如何做到这一点同时保留漂亮的印刷?

  1. JSON.stringify
console.log(JSON.stringify(obj, null, 2));
  1. console.dir
console.dir(obj, {
  depth: null,
});

console异步还是同步?

原问题:

https://stackoverflow.com/questions/23392111/console-log-async-or-sync

在Chrome和nodejs中分别执行以下代码

var obj = {};
console.log(obj);
obj.foo = 'bar';

nodejs结果:

{}

Chrome结果:
在这里插入图片描述
发生这种现象的原因是:

控制台将需要将记录的值存储在某处,并将其显示在屏幕上。渲染将会以异步方式发生(被限制到速率限制更新),以及将来与控制台中记录的对象的交互(如扩展对象属性)的交互。
因此,控制台可能会克隆(序列化)您记录的可变对象,也可能存储对它们的引用。第一个对深层物体不能很好地工作。此外,至少在控制台中的初始呈现可能会显示对象的“当前”状态,即当您记录的示例中的对象的状态Object {}。但是,当您扩展对象以进一步检查其属性时,控制台可能只存储对对象及其属性的引用,并且现在显示它们将显示其当前(已突变)状态。

简单来讲就是:WebKit的console.log并没有立即拍摄对象快照,相反,它只存储了一个指向对象的引用,然后在代码返回事件队列时才去拍摄快照。Node的console.log是另一回事,它是严格同步的,因此同样的代码输出的却为{}

参考:
console对象–详解
JavaScript 中 console 的用法
console 控制台 | Node.js API文档
控制台(console)| Node.js 中文文档 | Node.js 中文网
How to log an object in Node.js
console异步还是同步

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值