ADS2.4 JavaScript中的对象——日志对象

前端技术 everyinch 4135℃ 0评论

虽然在JavaScript中可以使用警告框来调试应用程序。但在进行某些DOM脚本编程时,很可能会遇到警告框的限制。例如,在研究DOM时,希望看看document对象都包含哪些方法和属性:

for (i in document) { alert(i); }

在Firefox中使用上面的循环会生成大约140次警告,那么多的警告框的确非常令人讨厌。现在要创建一个更好的方案,即使用浮动的调试日志随心所欲地记录日志消息。不再使用alert(),而是使用下面的对象:

for (i in document) { ADS.log.write(i); }

效果如下图所示:
ads2_logwindow
本示例创建的日志窗口只是定位在窗口中心、固定大小的<ul>元素。

myLogger对象

首先需要创建一个简单的HTML页面,其中包含ADS库和一个命名为myLogger.js的JavaScript文件。本示例通过实例化的ADS.log方法,随时使用ADS.log.write(‘log message’)方法来记录日志信息。基本的框架如下:

function myLogger(id) {

	id = id || 'ADSLogWindow';
	var logWindow = null;
	
	var createWindow = function () { };
	this.writeRaw = function (message) { };

}

myLogger.prototype = {
	write: function (message) {	},
	header: function (message) { }
};

if(!window.ADS) { window['ADS'] = {}; }
window['ADS']['log'] = new myLogger();

if(!console) var console = ADSLog;

myLogger对象具有如下特征:
1. myLogger是一个拥有私有、特权以及共有属性和方法的对象
2. myLogger对象也是一个构造函数,需要使用new关键字对其进行实例化
myLogger对象的每个成员都有特定的目的:
□ logWindow是一个私有属性,该属性将在内部被对象用来引用日志窗口的DOM节点
□ createWindow()是一个私有方法,用这个方法在DOM树中创建logWindow节点
□ writeRaw()是一个特权方法,该方法用于向日志窗口添加一条新记录。这个方法之所以是特权方法,是因为如果logoWindow尚未定义,它可以调用私有的createWindow()方法
□ write()是一个共有方法,它会对message中的尖括号进行编码,以便在日志窗口中显示HTML源代码。当message是一个对象并存在toString()方法时,调用对象的toString()方法。最终将编码后的message传递给writeRaw()方法
□ header()是一个共有方法,使用它来向日志窗口添加标题
在上述的代码结构中,共有方法是使用字面量语法定义的:

myLogger.prototype = {
    write: function(message) {},
    header: function(message) {}
};

当然,也可以使用点语法:

myLogger.prototype.write = function(message) {};
header.prototype.write = function(message) {};

如果打算向日志对象中添加更多的共有方法,那么使用字面量语法会减少冗余代码:

// 点语法
myLogger.prototype.write = function (message) {};
myLogger.prototype.header = function (message) {};
myLogger.prototype.link = function (link) {};
// 对象字面量
myLogger.prototype = {
    write: function (message) {},
    header: function (message) {},
    link: function (link) {}
};

1. myLogger.createWindow()方法

私有的createWindow()方法用来创建日志窗口。因为日志以列表项的形式表现,所以使用无序列表作为日志的容器元素。

createWindow(var createWindow = function () {

    // 将日志窗口定位在浏览器窗口的中心
    var browserWindowSize = ADS.getBrowserWindowSize();
    var top = ((browserWindowSize.height - 200) / 2) || 0;
    var left = ((browserWindowSize.width - 200) / 2) || 0;

    // 创建作为日志窗口的DOM节点
    logWindow = document.createElement('UL');

    // 指定它的id
    logWindow.setAttribute('id', id);

    // 定位日志窗口
    logWindow.style.position = 'absolute';
    logWindow.style.top = top + 'px';
    logWindow.style.left = left + 'px';

    // 设置固定的尺寸,并允许滚动
    logWindow.style.width = '200px';
    logWindow.style.height = '200px';
    logWindow.style.overflow = 'scroll';

    // 增加一些样式
    logWindow.style.padding= '0';
    logWindow.style.margin= '0';
    logWindow.style.border= '1px solid black';
    logWindow.style.backgroundColor= 'white';
    logWindow.style.listStyle= 'none';
    logWindow.style.font= '10px/10px Verdana, Tahoma, Sans';

    // 将其添加到文档中
    document.body.appendChild(logWindow);
};

createWindow()方法的两个关键部分:
首先,使用DOM方法createElement()创建一个无序列表,并将其赋值给私有的logWindow属性。在createWindow()方法的内部并没有定义logWindow变量,当赋值语句执行时,代码会到外部作用域中查找,于是在函数外部找到了私有的logWindow属性。
第二个关键部分是把logWindow添加到document.body中,这样会使它在浏览器中可见。私有的logWindow属性将维护一个指向相应DOM节点的引用。
createWindow()方法调用了ADS.getBrowserWindowSize()方法,其代码如下:

/**
 * 检索浏览器窗口的尺寸
 */
function getBrowserWindowSize() {
    var de = document.documentElement;
    
    // 对于大多数浏览器,使用 window.innerWidth
    // 对于strict mode的IE,使用 document.documentElement.clientWidth
    // 对于quirks mode的IE,使用document.body.clientWidth for MSIE in 
    
    return {
        'width':(
            window.innerWidth 
            || (de && de.clientWidth ) 
            || document.body.clientWidth),
        'height':(
            window.innerHeight 
            || (de && de.clientHeight ) 
            || document.body.clientHeight)
    }
};
window['ADS']['getBrowserWindowSize'] = getBrowserWindowSize;

2. myLogger.writeRaw()方法

特权方法writeRaw(),它负责真正地向logWindow添加新条目。writeRaw()方法创建列表项、为其添加样式、生成日志条目,最后将它添加到logWindow中。该方法的代码如下:

this.writeRaw = function (message) {

    // 如果不存在日志窗口,则创建它
    if(!logWindow) createWindow();

    // 创建列表项,并添加样式
    var li = document.createElement('LI');
    li.style.padding= '2px';
    li.style.border= '0';
    li.style.borderBottom = '1px dotted black';
    li.style.margin= '0';
    li.style.color= '#000';
    li.style.font = '9px/9px Verdana, Tahoma, Sans';

    // 将信息添加到日志节点
    if(typeof message == 'undefined') {
    	li.appendchild(document.createTextNode('Message was undefined'));
    } else if(typeof li.innerHTML != undefined) {
    	li.innerHTML = message;
    } else {
    	li.appendchild(document.createTextNode(message));
    }

    // 将列表项添加到日志窗口
    logWindow.appendChild(li);

    return this;
};

在创建和添加条目之前,需要先检测以下是否已经创建了日志窗口,如果没有,则调用私有的createWindow()方法。再有就是在为日志节点添加信息的过程中使用了innerHTML,对于innerHTML有一些争议,但innerHTML的确有很多优点:
□ 使用它比使用等价的DOM方法要少很多代码,而且也简单很多
□ 使用它可以使代码更清晰、更易读,因为它允许使用HTML字符串
□ 它的速度更快也更容易实现,因此效率更高
但innerHTML也有不少缺点:
□ 它可能会缺少长远的支持,因为它不是W3C规范中的内容
□ 它不维护对一个新创建的节点的引用
□ 它是一个针对浏览器中HTML的特性,对XML无效
□ 仅仅因为使用它更容易且速度更快,并不意味着就能开发出好的应用程序;很可能知识为自己懒惰找借口而已
下图展示了在ADS.log日志窗口中显示普通信息和<strong>标签的结果:
ads2_logwindow1

3. myLogger。write()方法和myLogger.header()方法

write()方法只是将writeRaw()方法包装起来,同时执行了一些额外的检测,将小于号和大于号转换成相应的代码。这样,传递到ADS.log.write()中的任何HTML代码都将以源代码形式显示在日志窗口中。使用header()方法可以添加一个标题,如下图所示:
ads2_logwindow2
为创建共有的write()和header()方法,把下列代码添加到myLogger对象的原型中:

myLogger.prototype = {

    /** 
     * 记录日志的共有方法
     * 对message中的尖括号进行编码,以便在日志窗口中显示HTML源代码
     * 当message是一个对象并存在toString()方法时,调用对象的toString()方法
     * 最终将编码后的message传递给writeRaw()方法
     */
    write: function (message) {
        // message为空值
        if(typeof message == 'string' && message.length==0) {
            return this.writeRaw('ADS.log: null message');
        }

        // 如果message不是String,则试图调用对象的toString()方法
        // 如果不存在toString()方法,则简单地记录对象的类型
        if (typeof message != 'string') {
            if(message.toString) return this.writeRaw(message.toString());
            else return this.writeRaw(typeof message);
        }

        // 将 < 和 > 转换为 &lt; 和 &gt;
        message = message.replace(/</g,"&lt;").replace(/>/g,"&gt;");

        return this.writeRaw(message);
    },


    /**
     * 输出一行标题
     */ 
    header: function (message) {
        message = '<span style="color:white;background-color:black;font-weight:bold;padding:0px 5px;">' + message + '</span>';
        return this.writeRaw(message);
    }
};

现在就可以将多种不同的信息记录到日志窗口中了。

分享&收藏

转载请注明:陈童的博客 » ADS2.4 JavaScript中的对象——日志对象

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
'; } if( dopt('d_footcode_b') ) echo dopt('d_footcode'); ?>