這個是jquery構造的問題,jquery官方非常多的提醒過這個,就是不要隨便用prototype,會影響到jquery的遍歷。
children的實現是壹個遍歷,妳自定義了壹個prototype,於是jquery就會遍歷到這個,但妳這個又是個函數,而不是壹個jquery對象
而當妳使用("#question_box p") 在jq內部就不是遍歷來實現的,而是find
find的實現
find:?function(?selector?)?{//?當表達式不包含“,”符號時候
if?(?this.length?===?1?&&?!/,/.test(selector)?)?{
var?ret?=?this.pushStack(?[],?"find",?selector?);
ret.length?=?0;
jQuery.find(?selector,?this[0],?ret?);
return?ret;
}?
//?當表達式包含“,”符號時候
else?{
var?elems?=?jQuery.map(this,?function(elem){
return?jQuery.find(?selector,?elem?);
});
return?this.pushStack(?/[^+>]?[^+>]/.test(?selector?)?
jQuery.unique(?elems?)?:
elems,?"find",?selector?);
}
}
//其中的jQuery.find是這樣壹個方法:
jQuery.find?=?Sizzle.find;
//而sizzle又是這樣壹個方法:
var?Sizzle?=?function(selector,?context,?results,?seed)?{
results?=?results?||?[];
context?=?context?||?document;
if?(?context.nodeType?!==?1?&&?context.nodeType?!==?9?)
return?[];
if?(?!selector?||?typeof?selector?!==?"string"?)?{
return?results;
}
var?parts?=?[],?m,?set,?checkSet,?check,?mode,?extra,?prune?=?true;
//?Reset?the?position?of?the?chunker?regexp?(start?from?head)
chunker.lastIndex?=?0;
while?(?(m?=?chunker.exec(selector))?!==?null?)?{
parts.push(?m[1]?);
if?(?m[2]?)?{
extra?=?RegExp.rightContext;
break;
}
}
if?(?parts.length?>?1?&&?origPOS.exec(?selector?)?)?{
if?(?parts.length?===?2?&&?Expr.relative[?parts[0]?]?)?{
set?=?posProcess(?parts[0]?+?parts[1],?context?);
}?else?{
set?=?Expr.relative[?parts[0]?]?
[?context?]?:
Sizzle(?parts.shift(),?context?);
while?(?parts.length?)?{
selector?=?parts.shift();
if?(?Expr.relative[?selector?]?)
selector?+=?parts.shift();
set?=?posProcess(?selector,?set?);
}
}
}?else?{
var?ret?=?seed?
{?expr:?parts.pop(),?set:?makeArray(seed)?}?:
Sizzle.find(?parts.pop(),?parts.length?===?1?&&?context.parentNodecontext.parentNode?:?context,?isXML(context)?);
set?=?Sizzle.filter(?ret.expr,?ret.set?);
if?(?parts.length?>?0?)?{
checkSet?=?makeArray(set);
}?else?{
prune?=?false;
}
while?(?parts.length?)?{
var?cur?=?parts.pop(),?pop?=?cur;
if?(?!Expr.relative[?cur?]?)?{
cur?=?"";
}?else?{
pop?=?parts.pop();
}
if?(?pop?==?null?)?{
pop?=?context;
}
Expr.relative[?cur?](?checkSet,?pop,?isXML(context)?);
}
}
if?(?!checkSet?)?{
checkSet?=?set;
}
if?(?!checkSet?)?{
throw?"Syntax?error,?unrecognized?expression:?"?+?(cur?||?selector);
}
if?(?toString.call(checkSet)?===?"[object?Array]"?)?{
if?(?!prune?)?{
results.push.apply(?results,?checkSet?);
}?else?if?(?context.nodeType?===?1?)?{
for?(?var?i?=?0;?checkSet[i]?!=?null;?i++?)?{
if?(?checkSet[i]?&&?(checkSet[i]?===?true?||?checkSet[i].nodeType?===?1?&&?contains(context,?checkSet[i]))?)?{
results.push(?set[i]?);
}
}
}?else?{
for?(?var?i?=?0;?checkSet[i]?!=?null;?i++?)?{
if?(?checkSet[i]?&&?checkSet[i].nodeType?===?1?)?{
results.push(?set[i]?);
}
}
}
}?else?{
makeArray(?checkSet,?results?);
}
if?(?extra?)?{
Sizzle(?extra,?context,?results,?seed?);
}
return?results;
};
而children的實現方法如下(children就是“>”)
relative:?{//
">":?function(checkSet,?part,?isXML){
//?當part為單詞字符時,如$("form?>?input"),part為“form”
if?(?typeof?part?===?"string"?&&?!/\W/.test(part)?)?{?
part?=?isXMLpart?:?part.toUpperCase();?
for?(?var?i?=?0,?l?=?checkSet.length;?i?<?l;?i++?)?{
var?elem?=?checkSet[i];
if?(?elem?)?{
//?得到elem的父節點
var?parent?=?elem.parentNode;
//?如果父節點名稱為part值時,在checkSet[i]上賦值父節點,否則賦值false
checkSet[i]?=?parent.nodeName?===?partparent?:?false;
}
}
//?當part為非單詞字符時,如$(".blue?>?input"),part為“.blue”
}?else?{
for?(?var?i?=?0,?l?=?checkSet.length;?i?<?l;?i++?)?{
var?elem?=?checkSet[i];
if?(?elem?)?{
checkSet[i]?=?typeof?part?===?"string"?
elem.parentNode?:
elem.parentNode?===?part;
}
}?
if?(?typeof?part?===?"string"?)?{
Sizzle.filter(?part,?checkSet,?true?);
}
}
},
}
看出區別了嗎?用的是Sizzle.filter
說道Sizzle,那是相當牛的壹個選擇器引擎,find和filter是其核心方法之壹,他們的區別可以看這個:
blogs.com/xesam/archive/2012/02/15/2352574.html
blogs.com/xesam/archive/2012/02/18/2356617.html
其中跟妳的問題有關的段落摘錄如下:
find直接用原生的getElementById(當然也會用byname或者其他)去找
Expr.find?=?{ID:?function(?match,?context,?isXML?)?{
if?(?typeof?context.getElementById?!==?"undefined"?&&?!isXML?)?{
var?m?=?context.getElementById(match[1]);
return?m?&&?m.parentNode[m]?:?[];?
}
},
//byclass?by?name是壹樣的實現
而children因為只找子壹級,不再往下找,所以采取的是兩次過濾的方法,即過濾questionbox的下壹級元素,然後再看是不是p標簽,(在jq的1.2以後的版本裏,這個過程是反過來的,似乎,即先找出所有p,然後再看父元素是不是妳前壹個篩選器,這個機制我記不太清了,懶得去翻源代碼看了,妳有興趣可以研究下)
那麽,這時候就要用到for in循環,而這時候妳又給所有對象定義了新的屬性,所以for in的時候必然遍歷到妳這個新屬性,妳這個自定義的屬性又不是個jq對象,於是自然杯具了。
但奇特的是,我反復測試了妳的代碼,發現在jq2.0以後的版本上似乎是沒問題的。。。難道jq改了選擇器的實現?