1

我只是想学习和理解 jQuery 源代码(到目前为止收效甚微 X_X),以提高我的 JavaScript 技能。随着我对 JavaScript 理解的增加,我想出了这个小日志/调试工具。就我的 JavaScript 水平而言,我在这里发布代码供人们判断和审核。因此,我有可能从所发表的评论中学习。有人可以指出潜在的问题,改进吗?我试图封装控制台实现并将其映射到 window.$console (唯一与全局范围混淆的地方)。

(function() {
    var proxy = {}, //use private proxy object to prevent binding to global (window) object
        _id = "",
        _warning = false;
        results = {};

    if (this.$console) { //check if $console exists in global (window)
        warning("$console is conflicting with existing object and could not be mapped.");
    }
    else {
        this.$console = proxy; //if undefined we then map proxy to global (window) object
    }

    proxy.init = function(id) { //map the display ol html element on the page
        _id = id;
        results = document.getElementById(id);
        return this;
    }

    proxy.log = function(msg) {
        append(msg);
        return this;
    };

    proxy.assert = function(pass, msg) {
        var html = (pass) ? "<b style=\"color: green;\">Pass</b>, " + msg
                    : "<b style=\"color: red;\">Fail</b>, " + msg ;
        append(html);
        return this;
    }

    proxy.error = function(msg) {
        var html = "<b style=\"color: red;\">Error</b>, " + msg + "";
        append(html);
        return this;
    }

    function append(msg) {
        if (results != null) {
            results.appendChild(getChild("li", msg));
        }
        else {
            warning("Message could not be appended to element with \"Id: " + _id + "\".");
        }
        return this;
    };

    function getChild(type, html) {
        var child = document.createElement(type);
        child.innerHTML = html;
        return child;
    }

    function warning(msg) {
        if (!_warning) {
            _warning = true;
            alert(msg);
        }
    }

    return proxy;
}());

用法

$console.init("console").log("hello world");
$console.assert(true, "This is a pass.");

ps:由于我对代码进行了一些修改,所以问题与最初的问题完全不同。

4

3 回答 3

4

似乎它可以正常工作。不过,我发现您对匿名函数的使用有点令人困惑。既然Console没有任何私有数据,为什么不这样定义:

var Console = {

    instance: document.getElementById('console'),

    Print: function (msg) {
        this.instance.innerHTML += msg;
        return this;
    },

    Log: function (msg) {
        this.Print("<br/>").Print(msg);
    }
};

我还删除了 的分配中使用的匿名函数instance,因为它似乎没有做任何事情。

编辑

匿名函数求值技术通常用于隐藏声明的变量。有关讨论,请参见http://yuiblog.com/blog/2007/06/12/module-pattern/

例如,如果您想隐藏该instance属性,您可以通过以下方式使用匿名函数来实现:

var Console = (function () {

    // object containing public members to be returned
    var c = {};

    // not visible outside anonymous function
    var instance = document.getElementById('console');

    // a 'public' property
    c.Print = function (msg) {
        instance.innerHTML += msg;
        return this;
    };

    // a 'public' property
    c.Log = function (msg) {
        this.Print("<br/>").Print(msg);
    };

    return c;
}());

生成的Console对象仅公开PrintLog属性。

于 2009-12-15T04:31:50.077 回答
2

到目前为止,我看到的唯一问题是您实际上是在公开两个全局变量,window.Console这很好,因为您想在那里公开它,并且$c.

这是因为你没有使用var对赋值语句进行赋值,应该是:

 var $c = this.Console;

如果你不使用它,$c它将是全球性的。

除此之外,也许您可​​能想要研究命名约定,通常在 JavaScript 中,您几乎将所有内容命名为camelCase,并且仅将构造函数命名为PascalCase,这只是一个注释,我个人尝试坚持该约定,但这取决于您和您的团队。

编辑:关于使用该innerHTML属性进行的连接,如果您要在 div 中处理大量数据,我建议您使用 DOM 操作,而不是innerHTML每次都替换整个数据。

通过 DOM 操作,我指的是使用和将日志消息创建为 div 的嵌套 DOM 元素。document.createElementelement.appendChild

于 2009-12-15T04:30:41.280 回答
0

我会尝试使用 Firebug 和 IE Developer Toolbar 公开的相同 API,以便您可以很好地降级。朝着这个方向的一个构建是如果 window.console 已经存在,那么不要执行你的代码。这样,您将在可用时获得本机调试器,否则您将获得您的实现。

于 2009-12-15T04:42:31.667 回答