代码改变世界
2009-02-18 07:56
贪婪的小猪
阅读(329 )
评论()
编辑
收藏
举报
Code
Object.prototype.each = function ()
{
// 由于HTML DOM不属于JavaScript对象,所以要迭代的话,必须
// 用下面的方式才能迭代,其中oHtmlDom是你要迭代的HTML DOM对象
// ({obj:oHtmlDom}).each(function(){var o = this;/* 这里省略你要写的代码 */});
// 这个变量在下面的匿名函数中会用到: _t
// bNlen 加了标志后控制深度迭代的时候性能大幅度提升
var _this = this .obj && [ this .obj] || this , arg = arguments, _t = this , bDepth, isHtml = false , bNlen, bThis = !! _this;
// 如果没元素进行迭代,就以一般的对象方式来迭代,然后就返回
if ( ! bThis || 0 == arg.length) return this ;
// 如果是String就拆分成数组
// 你知道为什么要用switch吗,请继续阅读后面的章节
switch (_this.constructor)
{
case String:
case Number:
case Boolean:
_this = String(_this).split( "" );
break ;
}
this .length = _this.length || 0 ;
// 这里提供可控制的迭代开始和结束点
// 支持外面使用bind技术设置内部的迭代开始和结束的下标
this ._eachPos || ( this ._eachPos = 0 );
this ._eachEnd || ( this ._eachEnd = _this.length);
// 下面的迭代匿名函数中的this是匿名函数自己的this,
// 因此这里定义一个匿名函数中能访问的变量,
// 虽然我们能使用bind来处理,但是会开销bind的时间
// 上面已经判断,这里就不判断了
// 支持迭代的时候,允许传入多个function,依次迭代执行
// 每一个迭代的function执行完所有元素的迭代后才回执行下一迭代器
switch ((bDepth = arg[arg.length - 1 ]).constructor)
{
case Boolean:
// 如果不是迭代函数而仅仅是标志就移除他
arg.pop();
break ;
default :bDepth = false ;
}
var i = 0 ;
// 兼容普通对象的迭代
if (_t._eachPos == _t._eachEnd)
{
if (Array != this .constructor && ! this .obj)
// 原本用i--性能会有提升的,但是这里不能这样
for (i = 0 ; i < arg.length; i ++ )
for ( var k in this )
arg[i].apply( this , [ this [k], k]);
return this ;
}
else try { do
{
var j = - 1 , k = _t._eachEnd - _t._eachPos, n = k % 8 , oN = n, oCurObj;
while (j ++ , 0 < n -- )
{
bNlen = false ;
oCurObj = _this[j];
// 兼容深度迭代能选择iframe,frame里的内容
// 增加bNs标志,表示不对内嵌的窗口进行处理
if ( ! _t[ ' bNs ' ] && !! oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
// 如果元素还可以迭代,并且要求深层迭代则继续迭代
// 如果深度迭代的是Array,则当前为Array的元素就不处理了
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
}
n = (k - oN) / 8 ;
while ( 0 < n -- )
{
// 由于这里对性能的要求很高,所以采用直接硬编码
bNlen = false ;
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 2
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 3
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 4
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 5
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 6
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 7
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
// 8
bNlen = false ;
oCurObj = _this[j];
if ( ! _t.bNs && oCurObj[ ' contentWindow ' ])arg[i].apply(oCurObj, [oCurObj, j]), oCurObj = _A(oCurObj.contentWindow.document.getElementsByTagName( " * " )),bNlen = true ;
if (bDepth || bNlen)
{
arg[i].apply(oCurObj, [oCurObj, j]);
if (oCurObj[ ' each ' ])oCurObj.each(arg[i], bDepth);
// 这里其实可以用_this[j].all的,但是那样会性能能更低
else if (oCurObj[ ' childNodes ' ] && 0 < oCurObj.childNodes.length)_A(oCurObj.childNodes).each(arg[i], bDepth);
else ( {obj:oCurObj} ).each(arg[i], bDepth);
}
else arg[i].apply(oCurObj, [oCurObj, j]);
j ++ ;
}
}while ( ++ i < arg.length)} catch (e) {}
return this ;
} ;
下面是jquery的each函数
Code
each: function ( object, callback, args ) {
var name, i = 0 , length = object.length;
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break ;
} else
for ( ; i < length; )
if ( callback.apply( object[ i ++ ], args ) === false )
break ;
// A special, fast, case for the most common use of each
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break ;
} else
for ( var value = object[ 0 ];
i < length && callback.call( value, i, value ) !== false ; value = object[ ++ i] ) {}
}
return object;
} ,