【问题标题】:JavaScript OOP: Implementation of LoggingJavaScript OOP:日志的实现
【发布时间】:2013-07-14 16:58:02
【问题描述】:

我编写了以下代码,通过使用 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 文件或方法访问?我的意思是我怎样才能做到private

任何指针都会对我很有帮助。

更新

从另一个SO thread我找到了关于私有方法的信息,我改变了我的方法:

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 未定义的错误。

【问题讨论】:

  • "在一个单独的 JS 文件中.." 听起来你是在说你实际上是通过 JS 将日志条目提交到一个 JS 文件中
  • 将“console”的所有实例重命名为“console2”等其他名称,以测试未定义的浏览器行为

标签: javascript oop


【解决方案1】:

回答你的问题:

  • 您的类实现有点奇怪。您正在使用闭包访问 console 变量,将其作为 Logger 上的属性更有意义。
  • 如果浏览器没有控制台,你不会得到错误(但记录器不会做任何事情)
  • 要使您的 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");

代码在此处作为 JSFiddle 提供:http://jsfiddle.net/mtufW/

【讨论】:

  • 谢谢 Rob,我有一个疑问。您已使用 this.console,但此控制台字段未在任何地方声明。我已经看到了工作示例。我想知道这个控制台是如何工作的?
  • 窗口对象被传递给函数。检查这段代码 Logger = function () { if (!w.console) { this.console = new DummyConsole(); } 其他 { this.console = w.console; } };
  • 是的,我以前看过这段代码。我担心的是,如果你使用this.console,那么在类范围内就会定义一些var console;。但事实并非如此,尽管代码运行良好。我的问题是如何?我们不需要在某处声明var console
  • 您在this 对象上定义console。在构造函数的上下文中是新创建的对象。类似于var a = {}; a.someProp = "hello";。你不需要var someProp,因为你在一个对象上定义它。
  • @TapasBose - 是的,你是对的:你可以定义一次,第二次只是为了证明如果控制台不可用,它将使用内部实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 2010-12-28
  • 1970-01-01
  • 2017-03-15
  • 2010-09-06
  • 2020-12-07
相关资源
最近更新 更多