QUnit 是 JavaScript单元测试框架。更加具体的介绍ref: http://qunitjs.com/
下面是QUnit中的一段代码:
( function () { function F() {} F.prototype = QUnit; QUnit = new F(); // Make F QUnit's constructor so that we can add to the prototype later QUnit.constructor = F; }());
What does it mean? I don't know. 直接把代码copy进浏览器中进行测试,同时定义
QUnit = { add: function (a, b){ return a+ b;}, id: 1 };
调试后发现:
根据元素id取得元素
function id( name ) { return !!( typeof document !== "undefined" && document && document.getElementById ) && document.getElementById( name ); }
!!感叹号的作用是什么??很显然不同于C/C++中的连续两次!。
他相当于三元运算符,返回boolean值。
var
ret = !!document.getElementById
Equals to the following:
var ret = document.getElementById ? true : false ;
Other practical techniques:
var num = 100 ; num = num +""; // var1+"" 转为 string document.write( typeof num+" : "+num+"<br/>" ); num = ~~num; // ~~var1 转为 int document.write( typeof num+" : "+num+"<br/>" ); num = [num] // [var1] 转为 array document.write( typeof num+" : "+"num instanceof Array"+(num instanceof Array)+" "+num+"<br/>");
// 为元素elem增加类型为type的事件,对应的函数为fn // 兼容Firefox,chrome及IE事件 function addEvent( elem, type, fn ) { if ( elem.addEventListener ) { elem.addEventListener( type, fn, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, fn ); } else { fn(); } }
// 把对象b中的属性和方法导出到对象a中 function extend( a, b ) { for ( var prop in b ) { if ( b[ prop ] === undefined ) { delete a[ prop ]; // Avoid "Member not found" error in IE8 caused by setting window.constructor } else if ( prop !== "constructor" || a !== window ) { a[ prop ] = b[ prop ]; } } return a; }
//异常栈中取得自己想要的信息
// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions) // Later Safari and IE10 are supposed to support error.stack as well // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack function extractStacktrace( e, offset ) { offset = offset === undefined ? 3 : offset; var stack, include, i, regex; if ( e.stacktrace ) { // Opera return e.stacktrace.split( "\n" )[ offset + 3 ]; } else if ( e.stack ) { // Firefox, Chrome stack = e.stack.split( "\n" ); if (/^error$/i.test( stack[0 ] ) ) { stack.shift(); } if ( fileName ) { include = []; for ( i = offset; i < stack.length; i++ ) { if ( stack[ i ].indexOf( fileName ) != -1 ) { break ; } include.push( stack[ i ] ); } if ( include.length ) { return include.join( "\n" ); } } return stack[ offset ]; } else if ( e.sourceURL ) { // Safari, PhantomJS // hopefully one day Safari provides actual stacktraces // exclude useless self-reference for generated Error objects if ( /qunit.js$/ .test( e.sourceURL ) ) { return ; } // for actual exceptions, this is useful return e.sourceURL + ":" + e.line; } } function sourceFromStacktrace( offset ) { try { throw new Error(); } catch ( e ) { return extractStacktrace( e, offset ); } }
好的类型检查实现
// Safe object type checking is: function ( type, obj ) { return QUnit.objectType( obj ) == type; }, objectType: function ( obj ) { if ( typeof obj === "undefined" ) { return "undefined" ; // consider: typeof null === object } if ( obj === null ) { return "null" ; } var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || "" ; switch ( type ) { case "Number" : if ( isNaN(obj) ) { return "nan" ; } return "number" ; case "String" : case "Boolean" : case "Array" : case "Date" : case "RegExp" : case "Function" : return type.toLowerCase(); } if ( typeof obj === "object" ) { return "object" ; } return undefined; },
在某一元素上触发事件
// Trigger an event on an element. // @example triggerEvent( document.body, "click" ); triggerEvent: function ( elem, type, event ) { if ( document.createEvent ) { event = document.createEvent( "MouseEvents" ); event.initMouseEvent(type, true , true , elem.ownerDocument.defaultView, 0, 0, 0, 0, 0, false , false , false , false , 0, null ); elem.dispatchEvent( event ); } else if ( elem.fireEvent ) { elem.fireEvent( "on" + type ); } },
判断是否在数组中存在某一元素
function inArray( elem, array ) { if ( array.indexOf ) { return array.indexOf( elem ); } for ( var i = 0, length = array.length; i < length; i++ ) { if ( array[ i ] === elem ) { return i; } } return -1 ; }
从元素中递归取得所有文本
function getText( elems ) { var i, elem, ret = "" ; for ( i = 0; elems[i]; i++ ) { elem = elems[i]; // Get the text from text nodes and CDATA nodes if ( elem.nodeType === 3 || elem.nodeType === 4 ) { ret += elem.nodeValue; // Traverse everything else, except comment nodes } else if ( elem.nodeType !== 8 ) { ret += getText( elem.childNodes ); } } return ret; }