在拿出插件之前,先回顧一下apply()的用法,這里和call()做比較。
JavaScript中的每一個Function對象都有一個apply()方法和一個call()方法,它們的語法分別為:
/*apply()方法*/ function.apply(thisObj[, argArray]) /*call()方法*/ function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);
它們各自的定義:
apply:應用某一對象的一個方法,用另一個對象替換當前對象。例如:B.apply(A, arguments);即A對象應用B對象的方法。
call:調用一個對象的一個方法,以另一個對象替換當前對象。例如:B.call(A, args1,args2);即A對象調用B對象的方法。
它們的共同之處:
都“可以用來代替另一個對象調用一個方法,將一個函數的對象上下文從初始的上下文改變為由thisObj指定的新對象”。
它們的不同之處:
apply:最多只能有兩個參數——新this對象和一個數組argArray。如果給該方法傳遞多個參數,則把參數都寫進這個數組里面,當然,即使只有一個參數,也要寫進數組里。如果argArray不是一個有效的數組或arguments對象,那么將導致一個TypeError。如果沒有提供argArray和thisObj任何一個參數,那么Global對象將被用作thisObj,並且無法被傳遞任何參數。並且apply具有打散參數的作用。
call:它可以接受多個參數,第一個參數與apply一樣,后面則是一串參數列表。這個方法主要用在js對象各方法相互調用的時候,使當前this實例指針保持一致,或者在特殊情況下需要改變this指針。如果沒有提供thisObj參數,那么 Global 對象被用作thisObj。
實際上,apply和call的功能是一樣的,只是傳入的參數列表形式不同。
以上只為更好的理解代碼,下面看代碼:
<script> //插件 (function () { /* * logEl 輸出的容器element * isInitialized 是否初始化 * _console */ var logEl, isInitialized = false, _console = {}; /* * 創建元素 * tag 標簽名稱 * css 樣式 */ function createElement( tag, css ) { var element = document.createElement( tag ); element.style.cssText = css; return element; } /* * 生成面板 * options 自定義樣式對象 */ function createPanel(options) { options.bgColor = options.bgColor || 'black'; options.color = options.color || 'lightgreen'; options.css = options.css || ''; var div = createElement( 'div', 'font-family:Helvetica,Arial,sans-serif;font-size:10px;font-weight:bold;padding:5px;text-align:left;opacity:0.8;position:fixed;right:0;top:0;min-width:200px;max-height:50vh;overflow:auto;background:' + options.bgColor + ';color:' + options.color + ';' + options.css); return div; } /* * 日志信息,自定義log方法 */ function log() { var el = createElement( 'div', 'line-height:18px;background:' + (logEl.children.length % 2 ? 'rgba(255,255,255,0.2)' : '')); // zebra lines var val = [].slice.call(arguments).reduce(function(prev, arg) {// return prev + ' ' + arg; }, ''); el.textContent = val; logEl.appendChild(el); // Scroll to last element logEl.scrollTop = logEl.scrollHeight - logEl.clientHeight; } /* * 清空控制台 */ function clear() { logEl.innerHTML = ''; } /* * 初始化插件,可以添加附加選項 */ function init(options){ if (isInitialized) { return; } isInitialized = true; options = options || {}; logEl = createPanel(options); document.body.appendChild(logEl); if (!options.freeConsole) { // 同步打印更新 _console.log = console.log; _console.clear = console.clear; console.log = originalFnCallDecorator(log, 'log'); console.clear = originalFnCallDecorator(clear, 'clear'); } } /* * 銷毀插件並恢復原來的控制台顯示 */ function destroy() { isInitialized = false; console.log = _console.log; console.clear = _console.clear; logEl.remove(); } /* * 驗證初始化 */ function checkInitialized(){ if (!isInitialized){ throw 'You need to call `screenLog.init()` first.'; } } function checkInitDecorator(fn){ return function(){ checkInitialized(); return fn.apply(this, arguments); }; } /* * 包含前台打印和后台打印 */ function originalFnCallDecorator(fn, fnName) { return function(){ //前台打印 fn.apply(this, arguments); if (typeof _console[fnName] === 'function') { //后台打印 _console[fnName].apply(console, arguments); } }; } window.screenLog = { init: init, log: originalFnCallDecorator(checkInitDecorator(log), 'log'), clear: originalFnCallDecorator(checkInitDecorator(clear), 'clear'), destroy: checkInitDecorator(destroy) }; })(); </script>
<script> screenLog.init(); screenLog.log('String: Hello world'); screenLog.log(21, 'multiple arguments'); screenLog.log('Arrays', [1, 2, 3]); console.log('console.log also gets logged.'); var i = 20; function log() { console.log('console log', Date.now()); if (--i) { setTimeout(log, 1000); } } log(); </script>
使用方法:
1.初始化插件
在頁面中引入screenlog.js文件。然后通過下面的方法來初始化該插件。
screenLog.init([option]);
初始化方法有一個附加選項option:
color:可自定義文本顏色
bgColor:可自定義背景顏色
freeConsole:默認情況下console.log會被在屏幕上重寫。你可以通過設置freeConsole為true
,並使用screenLog.log()
api來避免這種情況的發生。默認為false
。
2.screenLog.log(obj1[,obj2,obj2...,objn])
在屏幕上顯示的log信息。
obj1...objn:要被輸出的一組JavaScript對象或字符串。
3.screenLog.clear()
清空屏幕上的log信息。
4.screenLog.destory()
銷毀插件並恢復原來的控制台顯示。