<html> <head><meta http-equiv=content-type content="text/html; charset=utf-8"> <title>完美之绑定(bind)将通用于Object和Function,同时支持给Object增加[ ]运算符号</title> <style> html,body,td,p,div,span,th { font-size:9pt; } </style> </head> <body> <script type="text/javascript" language="JavaScript" src="/jcore/resource /javascript/Jcore.js"></script> <script type="text/javascript" language="JavaScript"> <!-- // 功能描述:封装用于大幅度提升常规for循环语句的性能, // 如果指定第4个参数为有效的非false参数,则表示倒过来循环 // 不过请注意,这里只是权宜封装,它依然不是最佳选择,欲知详情,参见第6章6.5节 // 返回信息:在function对象的时候返回绑定后的function对象,否则返回绑定后的对象 // 使用指南:例子代码比较多,这里就不给出使用举例了,请见下面的例子 // 应用范围:各种Web客户端和服务端开发 function FastFor(nStart,nForLen, oFunc) { try { FastFor.name = "FastFor"; var i = nStart || 0, myth = 8, nLen = nForLen - i, n = nLen % myth, nOld = n, arg = _A(arguments); // 移出前面3个参数 arg.splice(0,3); new function(){ // 倒过来循环 if(arg[3]) { i = nForLen; do{oFunc.apply(this, [].concat([i], arg)),i--}while(0 < --n); n = (nLen - nOld) / myth; while(0 < n--) { oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; oFunc.apply(this, [].concat([i], arg)),i--; } } else // 支持倒着循环 { do{oFunc.apply(this, [].concat([i], arg)),i++}while(0 < --n); n = (nLen - nOld) / myth; while(0 < n--) { oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; oFunc.apply(this, [].concat([i], arg)),i++; } }} }catch(e){fnCatch(e)} } // 功能描述:功能强大的通用对象的绑定实现,支持function // 这里出现后就提到"Jcore.js"里,以后章节将不再出现,而 // Jcore.js里原有的function的bind将删除,请读者注意 // 返回信息:在function对象的时候返回绑定后的function对象,否则返回绑定后的对象 // 使用指南:例子代码比较多,这里就不给出使用举例了,请见下面的例子 // 应用范围:各种Web客户端和服务端开发 Object.prototype.bind = function() { var a = _A(arguments), _this = this; switch(_this.constructor) { // JavaScript的case支持各种类型,这比其他编程语言强多了 // 针对Function的处理 // 不过要特别注意的是,Function的bind是要返回一个bind以后的函数的应用的 case Function: // 容错处理,防止bind的时候需要绑定NaN,undefined,null,Infinity等 !!a[0] || (a[0] = window); var b = _A(arguments); b.shift(); return function() { // b.concat(_A(arguments))是为了支持绑定返回的函数应用能再传入参数 // 如果要调整让传入的参数在最前面,那么_A(arguments).concat(b) // 换过来就可以了 return _this.apply(a[0], b.concat(_A(arguments))) }; break; case Object: a.each(function() { switch(this.constructor) { case Object: // 注意这里的this不等于_this // 它是a迭代器,迭代进来的a的每一个元素 for(var k in this) // bind就没有必要再覆盖了 // 读者请注意,这里常量放在逻辑比较运算符号的前面可以防止: // == 的时候少写了一个"="而很久都无法发现 // != 的时候少写了"!"却不轻易发现 if("bind" != k) _this[k] = this[k]; // 读者请注意:for in的方式无法枚举出:valueOf、toString、toLocaleString,这里做一个补偿 _this['toString'] = this['toString']; _this['valueOf'] = this['valueOf']; _this['toLocaleString'] = this['toLocaleString']; break; case Array: var _this1 = this; _this.length || (_this.length = 0); var n1 = _this1.length % 8, oN = n1; do { [].push.apply(_this, [_this1[i]]); }while(0 < n1--); n1 = (_this1.length - oN) / 8; do { [].push.apply(_this, [_this1[i]]);[].push.apply (_this, [_this1[i]]); [].push.apply(_this, [_this1[i]]);[].push.apply (_this, [_this1[i]]); [].push.apply(_this, [_this1[i]]);[].push.apply (_this, [_this1[i]]); [].push.apply(_this, [_this1[i]]);[].push.apply (_this, [_this1[i]]); }while(0 < n1--); // 或者:注意下面的注释方式,只需要在前面加一个"/"就可以激活代码了 /*///////////////// _this1.each(function() { // 注意这里的this不等于_this1 // 它是_this1迭代器,迭代进来的_this1的每一个元素 [].push.apply(_this, [this]); }); /////////////////*/ break; default: _this.length || (_this.length = 0); // 注意这里的this不等于_this // 它是a迭代器,迭代进来的a的每一个元素 [].push.apply(_this, [this]); }
}); return this; break; default:return _this; } };
// 测试函数的绑定 function fnTestFunctionBind() { var a = _A().concat(this); alert(a.join(" | ")) } // 这里支持两种形式,下面两行代码执行结果一样 // 都弹出: // 万物皆为我所用,但非我所属。| 你希望掌握永恒,那你必须控制现在。 | other | 945 // fnTestFunctionBind.bind(945, ["万物皆为我所用,但非我所属。", "你希望掌握永恒,那你必须控制现在。", "other"]) var oMyFct = fnTestFunctionBind.bind(945, "万物皆为我所用,但非我所属。", "你希望掌握永恒,那你必须控制现在。", "other"); // 效果参见图3-4 // 再次绑定 var oMyFct1 = oMyFct.bind(8888, "看轻别人很容易,要摆平自己却很困难。"); oMyFct("我新传递的参数", 20070804); // 结果参见图3-5 oMyFct1("第二个bind后调用", "其他参数"); // 别忘了养成良好的习惯,请注意, 这里的顺序也很讲究的 delete oMyFct1; delete oMyFct; // 这里用于测试Object的bind var oTestObject = { name:"从前的日子", display:function() { alert(this.name); } }; // 我们先测试最简单的支持 oTestObject.bind("one", "two", "three"); // 结果参见图3-6 alert([oTestObject[0], oTestObject[1], oTestObject[2]].join("\n\n")); // 测试混合绑定 oTestObject.bind(["four", "five", "six"], "单个String", 777); // 结果参见图3-7 alert(_A(oTestObject).join("\n\n")); // 这里我们测试绑定一个Object和一个Array进去 oTestObject.bind({ age: 150, fnDisplayAge:function() { return [this.name, this.age]; }, toString:function() { return "{name:'" + this.name + "',age:" + this.age + "}"; }}, ["第一个下标值", "人家怕你,并不是一种福,人家欺你,并不是一种辱。"]);
// 相当“perfect”地弹出了意愿中的结果,结果参见图3-8 alert(_A([_A(oTestObject).join("\n"), oTestObject.fnDisplayAge(), oTestObject.toString()]).join("\n")); --> </script> </body> </html> |