JavaScript的Console扩展和输出级别控制

扩展Console的原由

目前网上还没有类似的教程哦。
Console作为日志输出调试的功能还是很强大的。可以打印正常的日志信息,错误信息(log,info,warn,error)等等,还可以详细详细显示函数调用栈,信息的输出函数名以及代码位置,功能可谓非常强大。
这里写图片描述
但是有个问题就是无法根据日志的等级来自由控制输出权限。比如我设置一个等级,只能输出warn和error这样。虽然有可能发布的时候,会把Console基本有从代码中去掉,但是调试的时候有时也需要调整等级了。比如想暂时把log给屏蔽掉,只输出info或者warn以上信息。

最开始是想写个Log日志类来扩展Console的,增加控制日志等级之类的功能。写好之后,发现一个很郁闷的问题,那就是自己的日志输出,远远没有Console自带的强大。因为Console输出信息的时候,可以把当前类和那一行代码的信息给打印出来。这个很强大,对于调试非常有用,而自己写的Log没有这个功能。
用自己的Log进行扩展,则无法显示出真实的代码路径,变成自己写的Log路径了。看下图
这里写图片描述
当然这个输出日志路径是方便本地调试看。如果需要把日志错误等信息收集发给服务器,自定义扩展Log还是可行的。
针对这样的情况,我对Console对象进行了扩展。增加了相应的功能。

Console增加等级控制和扩展分析

演示代码为TypeScript的代码。后面会给出完整的TypeScript和JavaScript的代码。

1日志输出等级控制

首先是准备增加等级控制,比如我可以调整日志的输出级别,来决定trace,log,info,error等输出。原理其实很简单,利用原型重写对应的方法。根据等级,把小于日志输出等级的方法设置为一个空方法,什么也不做,这样就无法输出信息了。
对输出方法进行分级别

 /** 调试级别,trace函数路径 **/
 static TRACE:number = 0;
  /** 普通日志级别 **/
  static LOG:number = 1;
  /** 信息日志级别 **/
  static INFO:number = 2;
  /** 警告日志级别 **/
  static WARN:number = 3;
  /** 错误日志级别 **/
  static ERROR:number = 4;
  /** 需要屏蔽覆盖的方法名 **/
  private static funNames:string[] = ["trace","log","info","warn","error"];

实现过程是这样的:
先把console原来的trace,log等function给存放起来,当进行等级控制时,先把所有的方法都设置为空方法,然后把大于等于日志级别的方法给恢复过来。

//设置回最初的方法
 for(var i:number = 0; i < this.funNames.length; i++)
 {
     //定义个空方法屏蔽掉
     console[this.funNames[i]] = this.emptyFun;
 }
 //根据this.$level来还原输出方法
 for(var i:number = this.$level; i < this.funNames.length; i++)
 {
      //还原成最初的方法
      console[this.funNames[i]] = this.funList[i];
  }

原理就是这么简单,然后进行包装的代码就会稍微多一点。看输出效果。

// //开启扩展日志
asf.ConsolePlus.init();
console.log("扩展日志的正常模式");
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");
// console.error("error的信息");
console.log("把日志等级调整为WANR");
//设置日志等级,warn,就只有warn的信息才能输出
asf.ConsolePlus.setLevel(asf.ConsolePlus.WARN);
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");
console.error("error的信息");

输出结果是这样的
这里写图片描述
可以看到把日志等级调整为WARN之后,就无法看到log和info的信息了。

强化Console的输出方法

这个实现其实主要是后期扩展,需要把日志传给服务器或者其他调试端的时候才需要的。主要原理其实是在原有的log,info等方法的后面增加自己的信息(当然也可以发给服务器)。类似java的AOP面向切面编程。

/**
 * 创建扩展函数
 * @param oldFun 原有的函数
 * @param funName 函数名称
 */
private static createPlusFun(oldFun:Function,funName:string):void
{
    var fun:Function = function (message?: any, ...optionalParams: any[]):void
    {
        console.group("[" + funName + "][" + new Date() + "]");
        oldFun.apply(console,arguments);
        console.groupEnd();
    }
    this.funPulsList.push(fun);
}
asf.ConsolePlus.openConsolePlus();
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");

前后增加了个组显示的简单扩展,看具体的输出效果。
这里写图片描述

完整的TypeScritp和JavaScript代码

TypeScritp代码

/**
 * Created by sodaChen on 2017/3/1.
 */
namespace asf
{
    /**
     * 输出信息扩展类
     * @author sodaChen
     * Date:2017/2/15
     */
    export class ConsolePlus
    {
        /////////////////日志级别////////////////
        /** 调试级别,trace函数路径 **/
        static TRACE:number = 0;
        /** 普通日志级别 **/
        static LOG:number = 1;
        /** 信息日志级别 **/
        static INFO:number = 2;
        /** 警告日志级别 **/
        static WARN:number = 3;
        /** 错误日志级别 **/
        static ERROR:number = 4;

        /** 默认是最初的日志级别,改变这个值。可以改变日志输出的结果 **/
        private static $level:number = ConsolePlus.LOG;
        /** 是否开启扩展模式 **/
        private static isPlusMode:boolean;
        /** 需要屏蔽覆盖的方法名 **/
        private static funNames:string[] = ["trace","log","info","warn","error"];
        /** console最初的方法缓存 **/
        private static funList:Function[];
        /** 扩展后的方法级别 **/
        private static funPulsList:Function[];
        /** 空方法 **/
        private static emptyFun:Function;

        static init(isPlusMode:boolean = false):void
        {
            this.funList = [];
            this.funPulsList = [];
            this.emptyFun = function(){};

            //存放原来的方法
            for(var i:number = 0; i < this.funNames.length; i++)
            {
                this.funList.push(console[this.funNames[i]]);
            }
            //生成新的扩展方法
            for(var i:number = 0; i < this.funNames.length; i++)
            {
                this.createPlusFun(this.funList[i],this.funNames[i]);
            }
            this.setConsoleMode(isPlusMode);
        }

        /**
         * 设置日志等级,所有大于等于这个日志级别的输出都可以正常输出,小于的则不能进行输出
         * @param level
         */
        static setLevel(level:number):void
        {
            this.$level = level;
            this.openConsole();
        }
        /**
         * 设置输出模式
         * @param isPlusMode 是否为扩展模式
         */
        static setConsoleMode(isPlusMode:boolean):void
        {
            this.isPlusMode = isPlusMode;
            if(isPlusMode)
                this.openConsolePlus();
            else
                this.openConsole();
        }

        /**
         * 打开日志
         */
        static openConsole():void
        {
            this.closeConsole();
            //扩展默认,则调用扩展方法
            if(this.isPlusMode)
            {
                this.openConsolePlus();
                return ;
            }
            for(var i:number = this.$level; i < this.funNames.length; i++)
            {
                //还原成最初的方法
                console[this.funNames[i]] = this.funList[i];
            }
        }

        /**
         * 关闭所有的日志输出
         */
        static closeConsole():void
        {
            //设置回最初的方法
            for(var i:number = 0; i < this.funNames.length; i++)
            {
                //定义个空方法屏蔽掉
                console[this.funNames[i]] = this.emptyFun;
            }
        }

        /**
         * 开启日志输出的扩展模式
         */
        static openConsolePlus():void
        {
            this.isPlusMode = true;
            //扩展console的所有方法
            for(var i:number = this.$level; i < this.funNames.length; i++)
            {
                console[this.funNames[i]] = this.funPulsList[i];
            }
        }
        /**
         * 关闭日志输出的扩展模式
         */
        static closeConsolePlus():void
        {
            this.isPlusMode = false;
            //还原成原来的方法
            this.openConsole();
        }
        /**
         * 创建扩展函数
         * @param oldFun 原有的函数
         * @param funName 函数名称
         */
        private static createPlusFun(oldFun:Function,funName:string):void
        {
            var fun:Function = function (message?: any, ...optionalParams: any[]):void
            {
                console.group("[" + funName + "][" + new Date() + "]");
                oldFun.apply(console,arguments);
                console.groupEnd();
            }
            this.funPulsList.push(fun);
        }
    }
}

完整的调试信息代码:

// //开启扩展日志
asf.ConsolePlus.init();
console.log("扩展日志的正常模式");
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");
// console.error("error的信息");
console.log("把日志等级调整为WANR");
//设置日志等级,warn,就只有warn的信息才能输出
asf.ConsolePlus.setLevel(asf.ConsolePlus.WARN);
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");
console.error("error的信息");
//设置回正常的log级别
asf.ConsolePlus.setLevel(asf.ConsolePlus.LOG);
console.log("启动Console的扩展模式");
asf.ConsolePlus.openConsolePlus();
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");
console.error("error的信息");
//输出扩展模式也支持日志等级的
console.log("Console的扩展模式调整日志级别到warn");
asf.ConsolePlus.setLevel(asf.ConsolePlus.WARN);
console.log("log的信息");
console.info("info的信息");
console.warn("warn的信息");
console.error("error的信息");

asf.ConsolePlus.closeConsolePlus();
console.log("1关闭Console的扩展模式,正常输出啦");
//得调级别才能输出log
asf.ConsolePlus.setLevel(asf.ConsolePlus.LOG);
console.log("2关闭Console的扩展模式,正常输出啦");

JavaScript代码

注意,这个js代码是TypeScript生成的代码,所以有部分会很奇怪。具体我没单独调试运行过,请注意。

var asf;
(function (asf) {
    /**
     * 输出信息扩展类
     * @author sodaChen
     * Date:2017/2/15
     */
    var ConsolePlus = (function () {
        function ConsolePlus() {
        }
        ConsolePlus.init = function (isPlusMode) {
            if (isPlusMode === void 0) { isPlusMode = false; }
            this.funList = [];
            this.funPulsList = [];
            this.emptyFun = function () { };
            //存放原来的方法
            for (var i = 0; i < this.funNames.length; i++) {
                this.funList.push(console[this.funNames[i]]);
            }
            //生成新的扩展方法
            for (var i = 0; i < this.funNames.length; i++) {
                this.createPlusFun(this.funList[i], this.funNames[i]);
            }
            this.setConsoleMode(isPlusMode);
        };
        /**
         * 设置日志等级,所有大于等于这个日志级别的输出都可以正常输出,小于的则不能进行输出
         * @param level
         */
        ConsolePlus.setLevel = function (level) {
            this.$level = level;
            this.openConsole();
        };
        /**
         * 设置输出模式
         * @param isPlusMode 是否为扩展模式
         */
        ConsolePlus.setConsoleMode = function (isPlusMode) {
            this.isPlusMode = isPlusMode;
            if (isPlusMode)
                this.openConsolePlus();
            else
                this.openConsole();
        };
        /**
         * 打开日志
         */
        ConsolePlus.openConsole = function () {
            this.closeConsole();
            //扩展默认,则调用扩展方法
            if (this.isPlusMode) {
                this.openConsolePlus();
                return;
            }
            for (var i = this.$level; i < this.funNames.length; i++) {
                //还原成最初的方法
                console[this.funNames[i]] = this.funList[i];
            }
        };
        /**
         * 关闭所有的日志输出
         */
        ConsolePlus.closeConsole = function () {
            //设置回最初的方法
            for (var i = 0; i < this.funNames.length; i++) {
                //定义个空方法屏蔽掉
                console[this.funNames[i]] = this.emptyFun;
            }
        };
        /**
         * 开启日志输出的扩展模式
         */
        ConsolePlus.openConsolePlus = function () {
            this.isPlusMode = true;
            //扩展console的所有方法
            for (var i = this.$level; i < this.funNames.length; i++) {
                console[this.funNames[i]] = this.funPulsList[i];
            }
        };
        /**
         * 关闭日志输出的扩展模式
         */
        ConsolePlus.closeConsolePlus = function () {
            this.isPlusMode = false;
            //还原成原来的方法
            this.openConsole();
        };
        /**
         * 创建扩展函数
         * @param oldFun 原有的函数
         * @param funName 函数名称
         */
        ConsolePlus.createPlusFun = function (oldFun, funName) {
            var fun = function (message) {
                var optionalParams = [];
                for (var _i = 1; _i < arguments.length; _i++) {
                    optionalParams[_i - 1] = arguments[_i];
                }
                console.group("[" + funName + "][" + new Date() + "]");
                oldFun.apply(console, arguments);
                console.groupEnd();
            };
            this.funPulsList.push(fun);
        };
        /////////////////日志级别////////////////
        /** 调试级别,trace函数路径 **/
        ConsolePlus.TRACE = 0;
        /** 普通日志级别 **/
        ConsolePlus.LOG = 1;
        /** 信息日志级别 **/
        ConsolePlus.INFO = 2;
        /** 警告日志级别 **/
        ConsolePlus.WARN = 3;
        /** 错误日志级别 **/
        ConsolePlus.ERROR = 4;
        /** 默认是最初的日志级别,改变这个值。可以改变日志输出的结果 **/
        ConsolePlus.$level = ConsolePlus.LOG;
        /** 需要屏蔽覆盖的方法名 **/
        ConsolePlus.funNames = ["trace", "log", "info", "warn", "error"];
        return ConsolePlus;
    }());
    asf.ConsolePlus = ConsolePlus;
})(asf || (asf = {}));

完整的调试代码可以直接用上面那个ts的调试代码,使用过程是完全一样。(ts生成出来的那部分js也是一样的,不帖了)

发布了92 篇原创文章 · 获赞 72 · 访问量 78万+

猜你喜欢

转载自blog.csdn.net/sujun10/article/details/60878444