// 这里提供给HTML DOM对象迭代的简化写法
// 原本写({obj:oMyHtmlDom}).each(...)的,现在写J(oMyHtmlDom).each(...)就可以了
// 这里出现后将移进Jcore.js里,以后使用的地方将不再说明
// 使用举例
/*
// 'myTestDiv'.XPath()[0]其实也可以字节用'myTestDiv'就可以了
J('myTestDiv'.XPath()[0]).each(function()
{
// 如果有属性value就赋予其值, 注意,后面的( )使必须的,因为逻辑运算符号优先于赋值符号
'value' in this && (this.value = 'good');
}, true);
*/
var J = Object.prototype.J = function(o)
{
// 直接传递一个函数参数,就认为是要在页面加载完后执行
if("function" == typeof o)
{
fnAddEvent(window, "onload", o);
return this;
}
// 如果你希望设置回调函数的方式来处理XPath的结果,
// 可以在第二个参数设置回调函数,
// 回调函数的入口参数、上下文this就是XPath选择的结果
if(1 < arguments.length && Function == arguments[1].constructor)
{
var oCbkFunc = arguments[1];
fnRegCbkFun(function()
{
var a = J(o);
oCbkFunc.call(a, a);
delete a;
}, arguments[2] || 13);
return [];
}
var nCount = 0, szT;
// new XPath(o)的形式就兼容了传入id,nodeName或Xpath的 情况
o = String == o.constructor ? (Array == this.constructor ? this.XPath(o) : new XPath(o)) : _A(o);
// 支持动态的这样的行为设计的好处是功能强大,不随浏览器的升级而不支持
// 缺点是每次都需要对每个对象进行for in处理,效率会受到影响
// 所以我们以IE为标准,以53个事件为最大值来处理
// 如果你把下面注释的代码注释打开,那么就支持上面描述的功能
// 如果你不打开,我们已经在本代码的后面部分用静态的方式支持了
return o/*.each(function()
{
// 动态支持绑定N个事件的设计,即使是浏览器升级后有新的事件类型也支持
for(var k in this)
if(0 == k.indexOf("on"))
{
if(nCount >= 53)throw {message:"避免性能问题",jname:"J"};
szT = k.substr(2);
// !!!就是将变量转换为Boolean,判断他是不是“不”为真
if(!o[szT])
{
nCount++;if('click' == szT)alert("J: " + szT)
// 这样就支持J('myTest')['click'](function(){}) ... J('myTest')['change'](function(){})这样的方法了
o[szT] = (function(func)
{
// 这里提取出来的目的是下面的迭代器里将要用到他
var szTp = this.type;
// 迭代所有元素,都绑定func行为响应函数
return this._this.each(function(a,i)
{
fnAddEvent(this, szTp, func);
});
delete szTp;
// 这里将当前的对象和HTML对象以及绑定行为的事件名一起bind进去,好便于操作
}).bind({_this:o, obj:this, type:k});
}
}
})*/;
};
// 功能描述:注意,这里只是模拟多线程的运行,但是并不能真正的提高执行效率
// o是Object对象或function对象,成员有:
// clbkMsg: 执行完后返回的消息
// clbkObj: 需要将clbkMsg填写到HTML对象clbkObj上的value或innerHTML上
// clbkFun: 回调函数,必须只是处理循环中单轮的动作,比如你要启动多线程来清空
// 一个表格你的数据,保留原有的风格,那么你的clbkFun就只能处理单行、
// 列的数据,而处理哪行,则fnCreateMThread会给你传递进来;
// 如果不是不是循环,只是单个函数的非阻塞处理,
// 返回true就继续调用clbkFunc函数,否则就退出这样的
// 类似循环的调用,因此请注意你的回调函数的返回值,以防止死循环,
// 这时候的clbkFun没有任何入口参数
// ovFun : 执行完所有的循环、clbkFun后调用的函数,这样就比clbkMsg、clbkObj这两个参数更加灵活了
// nStart : 循环开始的数字,默认从0开始
// nEnd : 循环结束的数字
// nThrdNm: 开启的线程数,默认是每5个单轮处理一个线程
// nTime : 每次执行的间隔时间,默认是1毫秒,间隔时间越长,这操作界面就越流畅,不阻塞
// 如果传入的是function对象而没有任何的成员,那么就启动无阻塞的模式执行他
// 返回信息:返回当前对象
// 使用指南:
// 应用范围:各种Web客户端和服务端开发
function fnCreateMThread(o)
{
// 以对象方式允许,以便得到更优越的性能
if(window == this)
return new fnCreateMThread(o);//????为什么性能更加优越
// 同样,这里防止下面使用无效的o这个对象
o || (o = {});//???这边的逻辑是什么意思
o.nTime || (o.nTime = 13);
// 如果不是单纯的函数非阻塞运行??什么叫做非阻塞
if(o.nEnd && o.clbkFun)
{
// 默认从0开始,如果你没有设置他
o.nStart || (o.nStart = 0);
// 每个线程处理的次数
this.nL = 5;
// 线程执行完成数
this.nOvThrd = 0;
var n = o.nEnd - o.nStart, k, _this = this;
// 求每个线程需要处理的区段的次数
// 下面,以逗号运算符号,减少{ }中的一个字符的字节数
if(o.nThrdNm)
k = n % o.nThrdNm,
this.nL = (n - k) / o.nThrdNm + (0 < k ? 1 : 0);
else k = n % this.nL,
o.nThrdNm = (n - k) / this.nL + (0 < k ? 1 : 0);
// timer计数器
this.m_arrTmer = [];
// 启动多线程
for(var i = o.nStart; i < o.nEnd; i += this.nL)
{
this.nOvThrd++;
this.m_arrTmer.push(window.setInterval(function()
{//这边push是用来干嘛的push参数怎么可以是一个这么复杂的调用函数 if(this.nfEnd > this.nfStart)
{
// J("#myIpt" + this.pos)[0].value = [this.pos, this.nfEnd, this.nfStart].join(" | ");
// 传入当前处理的序号,和当前的线程号//这边的J应该是一个
o.clbkFun(this.nfStart++, this.pos);
}
else
{
_this.nOvThrd--;
// 结束当前的线程
window.clearInterval(_this.m_arrTmer[this.pos]);
if(0 == _this.nOvThrd)
{
// 注意:'value' in o.clbkObj 是判断对象时候有给定的属性,这比hasOwnProperty更加通用了
// 因为这样的方式不但支持JavaScript对象,同时也支持HTML DOM对象
if(o.ovFun)o.ovFun();
else
{
var s = '非阻塞模式函数执行完毕'; // 这里支持window和普通的HTML DOM对象或者输入对象
o.clbkObj && ('value' in o.clbkObj && (o.clbkObj.value = o.clbkMsg || s) ||
'innerHTML' in o.clbkObj && (o.clbkObj.innerHTML = o.clbkMsg || s) ||
'status' in o.clbkState && (o.clbkState.status = s) ||
'title' in o.clbkState && (o.clbkState.title = s) );
}
}
}
}.bind({pos:this.m_arrTmer.length, nfStart: i, nfEnd: i + this.nL}.bind(o)), o.nTime));
}
}
else// 普通不是循环函数的非阻塞模式启动
{
// nTm: timer 计数器
var nTm = 0, oFun = o.clbkFun || o;
nTm = window.setInterval(function()
{
// 这里我们为什么要加try...catch?因为如果要执行的代码还未执行,而窗口却已经关闭,就会发生:
// "不能执行已释放Script的代码"的错误
try
{
if(!oFun())
{
delete oFun;
window.clearInterval(nTm);
// 注意:'value' in o.clbkObj 是判断对象时候有给定的属性,这比hasOwnProperty更加通用了
// 因为这样的方式不但支持JavaScript对象,同时也支持HTML DOM对象
if(o.ovFun)return o.ovFun();
else
{
var s = '非阻塞模式函数执行完毕';
o.clbkObj && ('value' in o.clbkObj && (o.clbkObj.value = o.clbkMsg || s) ||
'innerHTML' in o.clbkObj && (o.clbkObj.innerHTML = o.clbkMsg || s) ||
'status' in o.clbkState && (o.clbkState.status = s) ||
'title' in o.clbkState && (o.clbkState.title = s) );
}
}
}catch(e){}
}, o.nTime);
}
return this;
}// 功能描述:将给的function当作无阻塞模式来运行
// 返回信息:返回无
// 使用指南:fnRegCbkFun(function(){要非阻塞方式执行的代码});
// 应用范围:各种Web客户端
function fnRegCbkFun(callback, nTm)
{
nTm || (nTm = 13);
new fnCreateMThread({clbkFun:function()
{
callback();
return false;
},nTime:nTm});
};// 功能描述:功能强大的通用对象的绑定实现,支持function
// 这里出现后就提到"Jcore.js"里,以后章节将不在出现,而
// Jcore.js里原有的function的bind将删除,请读者注意
// 返回信息:function对象的时候返回绑定后的function对象,否则返回绑定后的对象
// 使用指南:例子代码比较多,这里就不给出使用举例了,请见下面的例子
// 应用范围:各种Web客户端和服务端开发
Object.prototype.bind = function()
{
var a = _A(arguments), _this = this;
switch(_this['constructor'])
{
// 针对Function的处理
// 不过要特别注意的是,Function的bind是要返回一个bind以后的函数的应用的
case Function:
// 容错处理,防止bind的时候需要绑定NaN,undefined,null,Infinity等
!!a[0] || (a[0] = window);
// 克隆
var b = _A(a);
// 由于第一个是要绑定的对象,因此不作为下面的apply的参数,所以要移除出去
// 由于b是克隆出来的,因此移除第一个不会影响对象a
b.shift( );
// 注意这里返回的是函数对象,这就是对function绑定的特点
return function()
{
// b.concat(_A(arguments))是为了支持绑定返回的函数应用能再传入参数
// 如果要调整让传入的参数在最前面,那么_A(arguments).concat(b)换过来就可以了
// 为什么要写这两个for in,请见2.5节
var p = _this['prototype'], obj = a[0];
for(var k in p)
{
// 必须写这个if语句,否则覆盖了Object原型的方法,会导致错误
if(p[k] != Object.prototype[k])
obj[k] = this[k] = p[k];
}
p = obj['prototype'];
for(var k in p)
this[k] = p[k];
// alert(arguments[0]_this)
return _this.apply(a[0], b.concat(_A(arguments)));
};
break;
// case Object:
default:
a.each(function()
{
if(!('constructor' in this))
_this.push(this);
else switch(this.constructor)
{
case Object:
// 注意这里的this不等于_this
// 他是a迭代器,迭代进来的a的每一个元素
for(var k in this)
{
// bind就没有必要再覆盖了
// 读者朋友请注意,这里常量放在前面可以防止:
// == 的时候少写了一个"="而很久都无法发现
// != 的时候少写了"!"却不轻易发现
// 如果是函数,并且两个函数不相同,就做Super类似的处理
if(this[k] != Object.prototype[k] && _this[k] != this[k])
{
if("function" == typeof _this[k] && "function" == typeof this[k] && _this[k] != this[k])
// 如果不bind(_this),经过多次深层的Super后就找不到当前的this了
this[k].Super = _this[k].bind(_this);
_this[k] = this[k];
}
}
// 读者朋友请注意:for in的方式无法枚举出:valueOf、toString、toLocaleString,这里做一个补偿
this['toString'].Super = _this['toString'].bind(_this) , _this['toString'] = this['toString'];
this['valueOf'].Super = _this['valueOf'].bind(_this) , _this['valueOf'] = this['valueOf'];
this['toLocaleString'].Super = _this['toLocaleString'].bind(_this), _this['toLocaleString'] = this['toLocaleString'];
break;
case Array:
[].push.apply(_this, this);
break;
default:
// 注意这里的this不等于_this
// 他是a迭代器,迭代进来的a的每一个元素
[].push.apply(_this, [this]);
}
});
}
return this;
};
// 原本写({obj:oMyHtmlDom}).each(...)的,现在写J(oMyHtmlDom).each(...)就可以了
// 这里出现后将移进Jcore.js里,以后使用的地方将不再说明
// 使用举例
/*
// 'myTestDiv'.XPath()[0]其实也可以字节用'myTestDiv'就可以了
J('myTestDiv'.XPath()[0]).each(function()
{
// 如果有属性value就赋予其值, 注意,后面的( )使必须的,因为逻辑运算符号优先于赋值符号
'value' in this && (this.value = 'good');
}, true);
*/
var J = Object.prototype.J = function(o)
{
// 直接传递一个函数参数,就认为是要在页面加载完后执行
if("function" == typeof o)
{
fnAddEvent(window, "onload", o);
return this;
}
// 如果你希望设置回调函数的方式来处理XPath的结果,
// 可以在第二个参数设置回调函数,
// 回调函数的入口参数、上下文this就是XPath选择的结果
if(1 < arguments.length && Function == arguments[1].constructor)
{
var oCbkFunc = arguments[1];
fnRegCbkFun(function()
{
var a = J(o);
oCbkFunc.call(a, a);
delete a;
}, arguments[2] || 13);
return [];
}
var nCount = 0, szT;
// new XPath(o)的形式就兼容了传入id,nodeName或Xpath的 情况
o = String == o.constructor ? (Array == this.constructor ? this.XPath(o) : new XPath(o)) : _A(o);
// 支持动态的这样的行为设计的好处是功能强大,不随浏览器的升级而不支持
// 缺点是每次都需要对每个对象进行for in处理,效率会受到影响
// 所以我们以IE为标准,以53个事件为最大值来处理
// 如果你把下面注释的代码注释打开,那么就支持上面描述的功能
// 如果你不打开,我们已经在本代码的后面部分用静态的方式支持了
return o/*.each(function()
{
// 动态支持绑定N个事件的设计,即使是浏览器升级后有新的事件类型也支持
for(var k in this)
if(0 == k.indexOf("on"))
{
if(nCount >= 53)throw {message:"避免性能问题",jname:"J"};
szT = k.substr(2);
// !!!就是将变量转换为Boolean,判断他是不是“不”为真
if(!o[szT])
{
nCount++;if('click' == szT)alert("J: " + szT)
// 这样就支持J('myTest')['click'](function(){}) ... J('myTest')['change'](function(){})这样的方法了
o[szT] = (function(func)
{
// 这里提取出来的目的是下面的迭代器里将要用到他
var szTp = this.type;
// 迭代所有元素,都绑定func行为响应函数
return this._this.each(function(a,i)
{
fnAddEvent(this, szTp, func);
});
delete szTp;
// 这里将当前的对象和HTML对象以及绑定行为的事件名一起bind进去,好便于操作
}).bind({_this:o, obj:this, type:k});
}
}
})*/;
};
// 功能描述:注意,这里只是模拟多线程的运行,但是并不能真正的提高执行效率
// o是Object对象或function对象,成员有:
// clbkMsg: 执行完后返回的消息
// clbkObj: 需要将clbkMsg填写到HTML对象clbkObj上的value或innerHTML上
// clbkFun: 回调函数,必须只是处理循环中单轮的动作,比如你要启动多线程来清空
// 一个表格你的数据,保留原有的风格,那么你的clbkFun就只能处理单行、
// 列的数据,而处理哪行,则fnCreateMThread会给你传递进来;
// 如果不是不是循环,只是单个函数的非阻塞处理,
// 返回true就继续调用clbkFunc函数,否则就退出这样的
// 类似循环的调用,因此请注意你的回调函数的返回值,以防止死循环,
// 这时候的clbkFun没有任何入口参数
// ovFun : 执行完所有的循环、clbkFun后调用的函数,这样就比clbkMsg、clbkObj这两个参数更加灵活了
// nStart : 循环开始的数字,默认从0开始
// nEnd : 循环结束的数字
// nThrdNm: 开启的线程数,默认是每5个单轮处理一个线程
// nTime : 每次执行的间隔时间,默认是1毫秒,间隔时间越长,这操作界面就越流畅,不阻塞
// 如果传入的是function对象而没有任何的成员,那么就启动无阻塞的模式执行他
// 返回信息:返回当前对象
// 使用指南:
// 应用范围:各种Web客户端和服务端开发
function fnCreateMThread(o)
{
// 以对象方式允许,以便得到更优越的性能
if(window == this)
return new fnCreateMThread(o);//????为什么性能更加优越
// 同样,这里防止下面使用无效的o这个对象
o || (o = {});//???这边的逻辑是什么意思
o.nTime || (o.nTime = 13);
// 如果不是单纯的函数非阻塞运行??什么叫做非阻塞
if(o.nEnd && o.clbkFun)
{
// 默认从0开始,如果你没有设置他
o.nStart || (o.nStart = 0);
// 每个线程处理的次数
this.nL = 5;
// 线程执行完成数
this.nOvThrd = 0;
var n = o.nEnd - o.nStart, k, _this = this;
// 求每个线程需要处理的区段的次数
// 下面,以逗号运算符号,减少{ }中的一个字符的字节数
if(o.nThrdNm)
k = n % o.nThrdNm,
this.nL = (n - k) / o.nThrdNm + (0 < k ? 1 : 0);
else k = n % this.nL,
o.nThrdNm = (n - k) / this.nL + (0 < k ? 1 : 0);
// timer计数器
this.m_arrTmer = [];
// 启动多线程
for(var i = o.nStart; i < o.nEnd; i += this.nL)
{
this.nOvThrd++;
this.m_arrTmer.push(window.setInterval(function()
{//这边push是用来干嘛的push参数怎么可以是一个这么复杂的调用函数 if(this.nfEnd > this.nfStart)
{
// J("#myIpt" + this.pos)[0].value = [this.pos, this.nfEnd, this.nfStart].join(" | ");
// 传入当前处理的序号,和当前的线程号//这边的J应该是一个
o.clbkFun(this.nfStart++, this.pos);
}
else
{
_this.nOvThrd--;
// 结束当前的线程
window.clearInterval(_this.m_arrTmer[this.pos]);
if(0 == _this.nOvThrd)
{
// 注意:'value' in o.clbkObj 是判断对象时候有给定的属性,这比hasOwnProperty更加通用了
// 因为这样的方式不但支持JavaScript对象,同时也支持HTML DOM对象
if(o.ovFun)o.ovFun();
else
{
var s = '非阻塞模式函数执行完毕'; // 这里支持window和普通的HTML DOM对象或者输入对象
o.clbkObj && ('value' in o.clbkObj && (o.clbkObj.value = o.clbkMsg || s) ||
'innerHTML' in o.clbkObj && (o.clbkObj.innerHTML = o.clbkMsg || s) ||
'status' in o.clbkState && (o.clbkState.status = s) ||
'title' in o.clbkState && (o.clbkState.title = s) );
}
}
}
}.bind({pos:this.m_arrTmer.length, nfStart: i, nfEnd: i + this.nL}.bind(o)), o.nTime));
}
}
else// 普通不是循环函数的非阻塞模式启动
{
// nTm: timer 计数器
var nTm = 0, oFun = o.clbkFun || o;
nTm = window.setInterval(function()
{
// 这里我们为什么要加try...catch?因为如果要执行的代码还未执行,而窗口却已经关闭,就会发生:
// "不能执行已释放Script的代码"的错误
try
{
if(!oFun())
{
delete oFun;
window.clearInterval(nTm);
// 注意:'value' in o.clbkObj 是判断对象时候有给定的属性,这比hasOwnProperty更加通用了
// 因为这样的方式不但支持JavaScript对象,同时也支持HTML DOM对象
if(o.ovFun)return o.ovFun();
else
{
var s = '非阻塞模式函数执行完毕';
o.clbkObj && ('value' in o.clbkObj && (o.clbkObj.value = o.clbkMsg || s) ||
'innerHTML' in o.clbkObj && (o.clbkObj.innerHTML = o.clbkMsg || s) ||
'status' in o.clbkState && (o.clbkState.status = s) ||
'title' in o.clbkState && (o.clbkState.title = s) );
}
}
}catch(e){}
}, o.nTime);
}
return this;
}// 功能描述:将给的function当作无阻塞模式来运行
// 返回信息:返回无
// 使用指南:fnRegCbkFun(function(){要非阻塞方式执行的代码});
// 应用范围:各种Web客户端
function fnRegCbkFun(callback, nTm)
{
nTm || (nTm = 13);
new fnCreateMThread({clbkFun:function()
{
callback();
return false;
},nTime:nTm});
};// 功能描述:功能强大的通用对象的绑定实现,支持function
// 这里出现后就提到"Jcore.js"里,以后章节将不在出现,而
// Jcore.js里原有的function的bind将删除,请读者注意
// 返回信息:function对象的时候返回绑定后的function对象,否则返回绑定后的对象
// 使用指南:例子代码比较多,这里就不给出使用举例了,请见下面的例子
// 应用范围:各种Web客户端和服务端开发
Object.prototype.bind = function()
{
var a = _A(arguments), _this = this;
switch(_this['constructor'])
{
// 针对Function的处理
// 不过要特别注意的是,Function的bind是要返回一个bind以后的函数的应用的
case Function:
// 容错处理,防止bind的时候需要绑定NaN,undefined,null,Infinity等
!!a[0] || (a[0] = window);
// 克隆
var b = _A(a);
// 由于第一个是要绑定的对象,因此不作为下面的apply的参数,所以要移除出去
// 由于b是克隆出来的,因此移除第一个不会影响对象a
b.shift( );
// 注意这里返回的是函数对象,这就是对function绑定的特点
return function()
{
// b.concat(_A(arguments))是为了支持绑定返回的函数应用能再传入参数
// 如果要调整让传入的参数在最前面,那么_A(arguments).concat(b)换过来就可以了
// 为什么要写这两个for in,请见2.5节
var p = _this['prototype'], obj = a[0];
for(var k in p)
{
// 必须写这个if语句,否则覆盖了Object原型的方法,会导致错误
if(p[k] != Object.prototype[k])
obj[k] = this[k] = p[k];
}
p = obj['prototype'];
for(var k in p)
this[k] = p[k];
// alert(arguments[0]_this)
return _this.apply(a[0], b.concat(_A(arguments)));
};
break;
// case Object:
default:
a.each(function()
{
if(!('constructor' in this))
_this.push(this);
else switch(this.constructor)
{
case Object:
// 注意这里的this不等于_this
// 他是a迭代器,迭代进来的a的每一个元素
for(var k in this)
{
// bind就没有必要再覆盖了
// 读者朋友请注意,这里常量放在前面可以防止:
// == 的时候少写了一个"="而很久都无法发现
// != 的时候少写了"!"却不轻易发现
// 如果是函数,并且两个函数不相同,就做Super类似的处理
if(this[k] != Object.prototype[k] && _this[k] != this[k])
{
if("function" == typeof _this[k] && "function" == typeof this[k] && _this[k] != this[k])
// 如果不bind(_this),经过多次深层的Super后就找不到当前的this了
this[k].Super = _this[k].bind(_this);
_this[k] = this[k];
}
}
// 读者朋友请注意:for in的方式无法枚举出:valueOf、toString、toLocaleString,这里做一个补偿
this['toString'].Super = _this['toString'].bind(_this) , _this['toString'] = this['toString'];
this['valueOf'].Super = _this['valueOf'].bind(_this) , _this['valueOf'] = this['valueOf'];
this['toLocaleString'].Super = _this['toLocaleString'].bind(_this), _this['toLocaleString'] = this['toLocaleString'];
break;
case Array:
[].push.apply(_this, this);
break;
default:
// 注意这里的this不等于_this
// 他是a迭代器,迭代进来的a的每一个元素
[].push.apply(_this, [this]);
}
});
}
return this;
};
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货