function myLogger(id) { id = id || 'ADSLogWindow'; var logWindow = null; // 用受保护的方法创建日志窗口 var createWindow = function () { var browserWindowSize = ADS.getBrowserWindowSize(); var top = ((browserWindowSize.height - 300) / 2) || 0; var left = ((browserWindowSize.width - 300) / 2) || 0; // 创建作为日志窗口的DOM节点 // 使用受保护的 logWindow 属性维护引用 //使用DOM方法createElement()创建一个无序列表元素并将其赋值给私有的logWindow属性。为私有的logWindow赋值之所以有效,是因为createWindow()方法的内部作用域中没有定义logWindow的实例。当赋值语句执行时,代码会到外部作用域中查找,于是恰好找到了私有的logWindow属性。 logWindow = document.createElement('UL'); // 指定ID值,以便必要时在 DOM 树中能够识别它 logWindow.setAttribute('id', id); //在屏幕中居中定位日志窗口 if(client.browser.ie){ //alert(client.browser.ver); if(client.browser.ver <= 6){ logWindow.style.position = 'absolute'; }else{ logWindow.style.position = 'fixed'; } }else{ logWindow.style.position = 'fixed'; } logWindow.style.top = top + 'px'; logWindow.style.left = left + 'px'; logWindow.style.width = '300px'; logWindow.style.height = '300px'; logWindow.style.overflow = 'auto'; logWindow.style.padding = '0'; logWindow.style.margin = '0'; logWindow.style.border = '1px solid black'; logWindow.style.backgroundColor = 'white'; logWindow.style.listStyle = 'none'; document.body.appendChild(logWindow); }; this.writeRaw = function (message) { // 如果初始的窗口不存在,则创建它 //没有必要在私有的createWindow()方法前面加上this前缀。实际上,如果加上this前缀,该方法反而会无效。使用createWindow()要遵循与使用私有的logWindow成员相同的逻辑。当该方法被调用时,首先会检测函数的内部作用域,然后再检测外部作用域,这里的外部作用域是myLogger对象的构造函数,也就是私有的createWindow()方法所在的构造函数。而使用this.createWindow()也就相当于在对象的实例上调用createWindow(),但因为logWindow是私有的,所以会导致该方法无效。 if(!logWindow) createWindow(); // 创建列表项并适当地添加样式 var li = document.createElement('LI'); li.style.padding = '2px'; li.style.margin = '0'; li.style.border = '0'; li.style.borderBottom = '1px dotted black'; li.style.color = '#000'; //为日志节点添加信息 if(typeof message == 'undefined') { li.appendChild(document.createTextNode('Message was undefined')); }else if(typeof li.innerHTML != undefined) { //在这种情况下使用innerHTML会为你提供很多便利。当记录日志时,你可能希望记录原始的HTML并在日志窗口中将其作为HTML进行解析。这样,日志中的HTML将成为logWindow的DOM结构的组成部分(在调试时你必须知道这一点)。但此时要记录什么样的HTML却是未知的,因此也就无法简单地使用DOM方法来创建相应的结构。不过,从保险的角度考虑,你应该检测节点中是否存在innerHTML属性,如果不存在,则使用createTextNode()方法。 li.innerHTML = message; }else{ //虽然使用createTextNode()不会让浏览器将原始的HTML解析为DOM,但仍然能够保证将信息作为文本字符串显示在日志窗口中。 li.appendChild(document.createTextNode(message)); } //将这个条目添加到日志窗口 logWindow.appendChild(li); return this; }; } myLogger.prototype = { write: function (message) { //警告message为空值 if(typeof message == 'string' && message.length==0) { return this.writeRaw('ADS.log: null message'); } //如果message不是字符串,则尝试调用toString()方法,如果不存在该访问则记录对象类型 if(typeof message != 'string') { if(message.toString) return this.writeRaw(message.toString()); else return this.writeRaw(typeof message); } //转换<和>以便.innerHTML不会将message作为HTML进行解析 message = message.replace(/</g,"<").replace(/>/g,">"); return this.writeRaw(message); }, //向日志窗口中写入一个标题 header: function (message) { message = '<span style="display:block;padding:5px;color:white;background-color:black">' + message + '</span>'; return this.writeRaw(message); } }; if(!window.ADS) { window['ADS'] = {}; } window['ADS']['log'] = new myLogger(); if(!console) var console = ADS.log;