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;
}

