NODE源代碼 -- console

轉載:http://blog.csdn.net/leoleocs

// 指示javascript引擎切換到嚴格模式。
'use strict';
//引入工具類包,有一些幫助函數可以使用,這裏主要使用的是格式化的部分。
var util = require('util');
// 控制檯對象構造函數
//@stdout 標準輸出對象
//@stderr 標準錯誤輸出對象
function Console(stdout, stderr) {
  //檢查當前對象是否爲Console
  if (!(this instanceof Console)) {
    return new Console(stdout, stderr);
  }
  //檢查輸入參數, 確保輸入參數stdout對象上有write屬性,並且爲函數
  // 也就是說,只要對象上有write屬性,都可以爲stdout對象
  if (!stdout || !util.isFunction(stdout.write)) {
    throw new TypeError('Console expects a writable stream instance');
  }
  // 如果stderr的參數沒有被指定,直接使用stdout參數
  if (!stderr) {
    stderr = stdout;
  }
  //定義屬性
  var prop = {
    writable: true,
    enumerable: false,
    configurable: true
  };
  // 屬性值
  prop.value = stdout;
  //爲Console對象定義_stdout 屬性
  Object.defineProperty(this, '_stdout', prop);
  // 屬性值
  prop.value = stderr;
  //爲Console對象定義_stderr 屬性
  Object.defineProperty(this, '_stderr', prop);
  // 屬性值 
  prop.value = Object.create(null);
  //爲Console對象定義_times 屬性
  Object.defineProperty(this, '_times', prop);

  // bind the prototype functions to this Console instance
  var keys = Object.keys(Console.prototype);
  // 將原形方法上的屬性綁定到Console對象上。 
  for (var v = 0; v < keys.length; v++) {
    var k = keys[v];
    this[k] = this[k].bind(this);
  }
}
//總結上述Console的構造函數,其做了下面幾步:
//step1: 檢查參數,確保參數合法,默認stderr用stdout
//step2:  爲Console對象定義_stdeout, _stderr 等屬性
//step3:  將原型總的屬性或者方法拷貝到Console對象上。  

// 定義Console的原型方法log
Console.prototype.log = function() {
// 實質上就是調用_stdout 的write方法。手續需要格式化參數
  this._stdout.write(util.format.apply(this, arguments) + '\n');
};

// 實質上info函數是log函數的別名
Console.prototype.info = Console.prototype.log;

// 定義Console的原型方法warn 
Console.prototype.warn = function() {
  // 實質上就是調用_stderr的write方法。需要格式化參數
  this._stderr.write(util.format.apply(this, arguments) + '\n');
};

// 實質上error函數是warn函數的別名
Console.prototype.error = Console.prototype.warn;

// 直接輸出某個對象
Console.prototype.dir = function(object, options) {
  // 注意使用的還是_stdout屬相上的write方法
  // 不過在此前,其調用的工具類inspect方法去格式化具體的對象
  // 這個函數可以用於輸出Javascript對象進行調試分析
  this._stdout.write(util.inspect(object, util._extend({
    customInspect: false
  }, options)) + '\n');
};

// 時間函數, 計時開始函數
Console.prototype.time = function(label) {
  // 在times空對象上加入label屬性,屬性值爲當前時間,
  // 其實就是相當於開始計時函數 
  this._times[label] = Date.now();
};

// 時間函數, 計時結束函數,並且輸出時間

Console.prototype.timeEnd = function(label) {
  //讀取開始時間 
  var time = this._times[label];
  // 檢查是否有開始時間,如果沒有,直接拋出異常
  if (!time) {
    throw new Error('No such label: ' + label);
  }
  // 計算計時時間
  var duration = Date.now() - time;
   // 輸出計時時間
  this.log('%s: %dms', label, duration);
};

// 輸出當前的調用堆棧信息
Console.prototype.trace = function trace() {
  // TODO probably can to do this better with V8's debug object once that is
  // exposed.
  // 創建Error對象,並用全局函數Error.captureStackTrace來初始化
  // 堆棧信息
  var err = new Error;
  err.name = 'Trace';
  err.message = util.format.apply(this, arguments);
  Error.captureStackTrace(err, trace);
  // 利用error函數,也就是stderr屬性的write方法輸出
  this.error(err.stack);
};

// 基本等同於assert.ok的使用
// 只有第一個參數爲假的時候,會有作用,也就是出錯
Console.prototype.assert = function(expression) {
  if (!expression) {
    // 獲取格式化的參數,除掉第一個爲假的表達式  
    var arr = Array.prototype.slice.call(arguments, 1);
    // 只不過需要util.format格式化參數,也就是說,
    //這裏面可以使用'%d', '%s'等。
    require('assert').ok(false, util.format.apply(this, arr));
  }
};

// 導出的對象本身就是一個新的Console對象,注意使用的參數爲
// process.stdout, process.stderr
// 所以,我們可以直接用下面的用法:
// var tmpConsole = require('console')
// tmpConsole.log('test %d', 0); 
// 從官方文檔中,我們可以直接用全局的console對象。
module.exports = new Console(process.stdout, process.stderr);
// 導出Console的構造函數
//我們可以這麼用
// var Console = require('console').Console;
// var tmpConsole = new Console(process.stdout, process.stderr);
module.exports.Console = Console;

// 創建標準輸出對象到文件
var output = fs.createWriteStream('./stdout.log');
// 創建標準錯誤輸出對象到文件
var errorOutput = fs.createWriteStream('./stderr.log');
// 創建自己的Console對象
var logger = new Console(output, errorOutput);
var count = 5;
// 直接輸出到文件stdout.log中
logger.log('count: %d', count);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章