util模块是一类包罗万象的模块。今天测试一下它的一些方法,提供了实用函数来格式化字符串,将对象转换为字符串,检查对象的类型,并执行对输出流的同步写入,以及一些对象继承的增强。


1、格式化字符串  

format <string> 一个类似 printf 的格式字符串。

util.format() 方法返回一个格式化后的字符串,使用第一个参数作为一个类似 printf 的格式的字符串,该字符串可以包含零个或多个格式占位符。 每个占位符会被对应参数转换后的值所替换。

支持的占位符有:

%s - String 将用于转换除 BigInt、 Object 和 -0 外的所有值。BigInt 值将用 n 表示,而没有用户定义 toString 函数的对象使用带有选项 { depth: 0, colors: false, compact: 3 } 的 util.inspect() 进行检查。

%d - Number 将用于转换除 BigInt 和 Symbol 之外的所有值。

%i - parseInt(value, 10) 用于除 BigInt 和 Symbol 之外的所有值。

%f - parseFloat(value) 用于除 BigInt 和 Symbol 之外的所有值。

%j - JSON。如果参数包含循环引用,则替换为字符串 '[Circular]'。

%o - Object。具有通用 JavaScript 对象格式的对象的字符串表示形式。 类似于带有选项 { showHidden: true, showProxy: true } 的 util.inspect()。 这将显示完整对象,包括非可枚举属性和代理。

%O - Object。具有通用 JavaScript 对象格式的对象的字符串表示形式。 类似于 util.inspect() 但没有选项。 这将显示完整对象,不包括非可枚举属性和代理。

%c - CSS。该说明符当前会被忽略,将会跳过任何传入的 CSS。

%% - 单个百分号('%')。这不会消耗参数。

返回: <string> 格式化的字符串。

案例:

/**如果占位符没有对应的参数,则占位符不被替换。*/
util.format('%s:%s', 'foo');
返回: 'foo:%s'

/**如果类型不是 string,则使用 util.inspect() 格式化不属于格式字符串的值。*/

/**如果传入 util.format() 方法的参数比占位符的数量多,则多出的参数会被强制转换为字符串,然后拼接到返回的字符串,参数之间用一个空格分隔。*/
util.format('%s:%s', 'foo', 'bar', 'baz');
返回: 'foo:bar baz'

/**如果第一个参数不是一个字符串,则 util.format() 返回一个所有参数用空格分隔并连在一起的字符串。*/
util.format(1, 2, 3);
返回: '1 2 3'

/**如果只有一个参数传给 util.format(),它将按原样返回,不带任何格式:*/
util.format('%% %s');
返回: '%% %s'

注意: util.format() 是一种用作调试工具的同步方法。 某些输入值可能会产生严重的性能开销,从而阻止事件循环。 请谨慎使用此功能,切勿在热代码路径中使用。


2,检查对象类型   

util.types 提供了针对不同类型的内置对象的多种类型检查。与实例或 Object.toString.call(value)不同,这些检查不检查可从 JavaScript(如其原型)访问的对象的属性,并且通常具有调用C++的开销。

结果通常不会保证值在 JavaScript 中公开的属性或行为类型。它们主要适用于喜欢在 JavaScript 中执行类型检查的加载项开发人员。(原util下的isXXX方法已经被废弃

常用变量类型判断,另参考:JavaScript中typeof、instanceof、Object.prototype.toString.call(value)用法及区别


3、util.debuglog(section)   

util.debuglog() 方法用于创建一个函数,基于 NODE_DEBUG 环境变量的存在与否有条件地写入调试信息到 stderr。 如果 section 名称在环境变量的值中,则返回的函数类似于 console.error()。 否则,返回的函数是一个空操作。

const util = require('util');
const debuglog = util.debuglog('foo');

/**
* 如果程序在环境中运行时带上 NODE_DEBUG=foo,则输出类似如下:
* FOO 3245: hello from foo [123]
* 其中 3245 是进程 id。 如果运行时没带上环境变量集合,则不会打印任何东西。
*/
debuglog('hello from foo [%d]', 123);

section 还支持通配符:

const util = require('util');
const debuglog = util.debuglog('foo-bar');

/**
* 如果在环境中使用 NODE_DEBUG=foo* 运行,那么它将输出如下内容:
* FOO-BAR 3257: hi there, it's foo-bar [2333]
* NODE_DEBUG 环境变量中可指定多个由逗号分隔的 section 名称。 例如:NODE_DEBUG=fs,net,tls
*/
debuglog('hi there, it\'s foo-bar [%d]', 2333);


4、将JavaScript对象转换为字符串   

    通常,尤其是调试的时候,你需要把一个JavaScript对象转换为字符串表示。util.inspect()方法允许你检查一个对象,然后返回该对象的字符串表示形式。

    下面是inspect()方法的语法:

    util.inspect(object,[options])

    object参数是要转换为字符串的JavaScript对象。options方法可以让你控制格式化过程的某些方面。

const util = require('util');

let a = {a:1,b:2};
console.log(typeof a === 'object');//输出为true

let aa = util.inspect(a);
console.log(typeof aa === 'string');//输出为true


5、从其他对象继承功能   

    util模块提供了util.inherits()方法来允许你创建一个继承另一个对象的prototype(原型)方法的对象。当你创建一个新的对象时,prototype方法自动被使用。例如,实现自己的自定义Readable和Writable流的时候。

    以下是util.inherits()方法的语法:util.interits(constructor,superConstructor)

    原型constructor被设定为原型superConstructor,并在一个新的对象被创建时执行。你可以通过使用constructor.super_属性从你的自定义对象的构造函数访问superConstructor。

    下面清单中的代码说明了使用inherits()继承events.EventEmitter对象构造函数来创建一个Writable流。

const util = require("util");
let events = require("events");

function Writer(){
events.EventEmitter.call(this);
}

util.inherits(Writer,events.EventEmitter);

Writer.prototype.write = function(data){
this.emit("data",data);
};

let w = new Writer();
console.log(w instanceof events.EventEmitter);
console.log(Writer.super_ === events.EventEmitter);

w.on("data",function(data){
console.log('Received data:"' + data + '"');
});

w.write("Some Data!");


6、util.callbackify(original)      新增于: v8.2.0   

original <Function>  async 异步函数。

返回: <Function> 传统回调函数。

将 async 异步函数(或者一个返回值为 Promise 的函数)转换成遵循异常优先的回调风格的函数,例如将 (err, value) => ... 回调作为最后一个参数。 在回调函数中,第一个参数为拒绝的原因(如果 Promise 解决,则为 null),第二个参数则是解决的值。

const util = require('util');

async function fn() {
return 'hello world';
}

const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {
if (err) throw err;
console.log(ret);
});

将会打印出:hello world

回调函数是异步执行的,并且有异常堆栈错误追踪。 如果回调函数抛出一个异常,进程会触发一个 'uncaughtException' 异常,如果没有被捕获,进程将会退出。

null 在回调函数中作为一个参数有其特殊的意义,如果回调函数的首个参数为 Promise 拒绝的原因且带有返回值,且值可以转换成布尔值 false,这个值会被封装在 Error 对象里,可以通过属性 reason 获取。

const util = require('util');

function fn() {
return Promise.reject(null);
}

const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {
// Promise 被以 `null` 拒绝时,它被包装为 Error 并且原始值存储在 `reason` 中。
err && err.hasOwnProperty('reason') && err.reason === null; // true
});