Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript-OOP:日志记录的实现_Javascript_Oop - Fatal编程技术网

JavaScript-OOP:日志记录的实现

JavaScript-OOP:日志记录的实现,javascript,oop,Javascript,Oop,我已经编写了以下代码,通过使用OOP在单独的js文件logger.js中实现日志记录 var console; function Logger() { init(); } var init = function() { if(!window.console){ console = { log: function(message){}, info: function(message){},

我已经编写了以下代码,通过使用OOP在单独的js文件logger.js中实现日志记录

var console;

function Logger() {
    init();
}

var init = function() {
    if(!window.console){ 
        console = {
            log: function(message){},
            info: function(message){},
            warn: function(message){},
            error: function(message){}
        }; 
    } else {
        console = window.console;
    }
};

Logger.prototype.log = function(message) {
    console.log(message);    
}

Logger.prototype.logInfo = function(message) {
    console.info(message);
}

Logger.prototype.logWarn = function(message) {
    console.warn(message);
}

Logger.prototype.logError = function(message) {
    console.error(message);
}
我从另一个js文件site.js中使用它:

var logger = new Logger(); //global variable

var getComponentById = function(id) {
    var component = null;

    if(id) {
        try {
            component = AdfPage.PAGE.findComponentByAbsoluteId(id);
        }catch(e){
            logger.logError(e);
        }
    }

    return component;
}
我在想

  • 如果我通过维护JavaScript的OOP以正确的方式实现了
    Logger
  • 它能处理浏览器没有任何控制台的情况吗
  • 如何使
    init()
    方法无法从其他js文件或方法访问?我的意思是,我怎样才能使它成为私有的
任何指针都会对我很有帮助

更新 我从另一个网站上找到了关于私有方法的信息,并改变了我的方法:

function Logger() {
    init();
}

Logger.prototype = (function() {
    var console;

    var init = function() {
        if(!window.console){ 
            this.console = {
                log: function(message){},
                info: function(message){},
                warn: function(message){},
                error: function(message){}
            }; 
        } else {
            this.console = window.console;
        }
    };

    return {
        constructor: Logger,

        log: function(message) {
            this.console.log(message);    
        },

        logInfo: function(message) {
            this.console.info(message);
        },

        logWarn: function(message) {
            this.console.warn(message);
        },

        logError: function(message) {
            this.console.error(message);
        }
    };
})();

但在这种情况下,我得到的错误是未定义
init

要回答您的问题:

  • 您对该类的实现有点奇怪。使用闭包访问
    控制台
    变量,将其作为记录器上的属性更有意义
  • 如果浏览器没有控制台,则不会出现错误(但记录器不会执行任何操作)
  • 要使init函数私有,可以将其包装在IIFE(立即调用的函数表达式)中
我接受了您的代码并对其进行了轻微更改,以得出以下结论:

// Create the Logger function with an IIFE, this keeps all of the private
// variables out of the global scope, the only thing in the global scope
// is the function returned by the IIFE.
var Logger = (function (w) {
    var Logger,
        DummyConsole;

    DummyConsole = function () {
        this.log = function (message) {
            alert(message);
        };
        this.info = function (message) {
            // Implement however you want.
        };
        this.warn = function (message) {
            // ... 
        };
        this.error= function (message) {
            // ...
        };
    };

    Logger = function () {
        if (!w.console) {
            this.console = new DummyConsole();
        } else {
            this.console = w.console;
        }
    };

    Logger.prototype.log = function(message) {
        this.console.log(message);    
    };

    Logger.prototype.logInfo = function(message) {
        this.console.info(message);
    };

    Logger.prototype.logWarn = function(message) {
        this.console.warn(message);
    };

    Logger.prototype.logError = function(message) {
        this.console.error(message);
    };

    return Logger;
}(window));

// create a logger instance to check that the Logger class logs to the console.
var a = new Logger();
a.log("hello");

// Remove the console.
window.console = null;

// Create a new logger checking that it falls back to the dummy console implementation.
var b = new Logger();

// An (annoying) alert is shown.
b.log("Hi");

代码可以作为JSFIDLE在这里使用:

“在一个单独的JS文件中…”听起来好像你说你实际上是要通过JSIDLE将日志条目提交到一个JS文件中。将“console”的所有实例重命名为诸如“console2”之类的其他东西来测试浏览器行为,如果没有定义的话。谢谢Rob,我有一个疑问。您使用了this.console,但未在任何地方声明此控制台字段。我已经看到了工作示例。我想知道这个控制台是如何工作的?窗口对象被传递给函数。检查这段代码Logger=function(){if(!w.console){this.console=new dummconsole();}否则{this.console=w.console;};是的,我以前见过这个代码。我担心的是,如果您使用
this.console
,那么就会有
var控制台在类范围中定义。但事实并非如此,尽管代码运行良好。我的问题是怎么做?我们不需要在某个地方声明
var console
?您正在
这个
对象上定义
console
。在构造函数的上下文中是新创建的对象。类似于
var a={};a、 someProp=“你好”。在对象上定义someProp时,您不需要
var someProp
。@TapasBose-是的,您是对的:您可以只定义一次,第二次只是为了证明如果控制台不可用,它将使用内部实现。