
SystemPoster
-
个人空间
相册
- 性别:
- 来自:
- 积分:7433
- 帖子:7194
- 注册:
2007-07-18
|
JavaScript写作技巧,函数A中调用函数B, 怎样在函数B中写代码中断函数A的运行?
function funcA(){ funcB(); //other code } 怎么定义函数B,让B在运行的时候不仅能终止B本身,而且能终止函数A的运行? 这是个非常规的问题,我们分两大部分讨论. (1.为什么一定这样做 2.怎么实现) 1. 显然,这种编码方式已经打乱了正规的程序编写原则,我们编写函数的目的就是为了封装,为了实现代码的模块化. 如果B能让A退出返回, 那这种编码方式肯怕比滥用 goto 语句还滥了. 这样做有必要吗?为什么一定要这样做....?? 答案如下: 假如我们要扩展Array的prototype. 比方说:定义一个 find方法,用来返回第一个让 执行函数为真的数组元素. 1 <script> 2 // by go_rush(阿舜) @ http://ashun.cnblogs.com 3 4 Array.prototype.each=function(f){ 5 for(var i=0;i<this.length;i ) f(this ,i,this) 6 } 7 8 Array.prototype.find=function(f){ 9 var result; 10 this.each(function(value,index,arr){ 11 if (f(value,index,arr)) result=value 12 }) 13 return result 14 } 15 16 var arr=[1,2,3,4,5,7,9] 17 18 function foo(v){ //检测是不是偶数 19 return v%2==0 20 } 21 alert(arr.find(foo)) 22 23 </script> 结果另我们大失所望. 首先: 在逻辑上,程序是错误的,因为我们期望返回第一个偶数,但是程序却返回的是最后一个偶数. 其次: 程序的效率是低下的,那怕是找最后一个偶数,他在找到偶数4后,仍然检测了4后面的所有元素.这个动作 是多余的. 怎么办呢? 请看代码中的第11行,如果检测到 f(value,index,arr) 为真的时候,能够直接中断函数 this.each()该多好啊. 效率,结果,双赢的局面. 所以对于问题一 "为什么一定这样做" , 在这里,具体到这个应用上,有足够的理由让函数 B()来中断函数A() 看到这里,你可能会问: 你的 find 方法为什么不这样写? Array.prototype.find=function(f){ for(var i=0;i<this.length;i ){ if (f(this,i,this)) return this } } 这样不整个世界都清净了吗. 是的,如果我只是简单的写一个find 这样写肯定没问题,但是如果现在我正在写一个复杂的应用,或一个写一个js框架呢 我要实现一系列的 Array.prototype.all Array.prototype.any Array.prototype.each Array.prototype.map Array.prototype.find Array.prototype.findAll Array.prototype.grep Array.prototype.inject ...... 详细请参见 prototype.js v1.4 有上十种方法等着实现呢,我怎不可能每个方法都用 for循环一个一个的 遍历数组把. 我肯定要实现一个 each 方法作为统一入口吧. 闲话少说,我们来看怎么解决问题: 要在 B函数中终止A函数,并返回结果, 目前我能想到的办法就是用异常 try{}catch(x){}
实现代码 1 <script> 2 // by go_rush(阿舜) @ http://ashun.cnblogs.com
3 4 var $break=new Object() 5 6 Array.prototype.each=function(f){ 7 try{ 8 for(var i=0;i<this.length;i ){ 9 try{ 10 f(this,i,this) 11 }catch(e){ 12 if (e==$break) throw e 13 } 14 } 15 }catch(e){ 16 } 17 } 18 19 Array.prototype.find=function(f){ 20 var result; 21 this.each(function(value,index,arr){ 22 if (f(value,index,arr)){ 23 result=value 24 throw $break 25 } 26 }) 27 return result 28 } 29 30 var arr=[1,2,3,4,5,7,9] 31 32 function foo(v){ //检测是不是偶数 33 return v%2==0 34 } 35 alert(arr.find(foo)) 36 37 </script> 在第24行,如果程序已经找到第一个满足函数返回值为真的元素,那么就抛出一个自定义异常,终止 this.each()的 运行.. 注意第12行,只有确保函数抛出的是自定义异常才继续向上抛出异常,从而终止函数的运行. 在上面的代码中,我用的 try---catch方法完全是用来解决本贴所提出的问题的,并未进行任何其他错误处理. 在这方面,prototype.js ,通过定义两个自定义异常对象 $break 和 $continue ,既照顾到了异常处理,又解决了本贴 提出的问题. Enumerable 对象实现得很优雅, 大家不妨再去体会体会 prototype.js 中Enumerable的妙处. 我们看看prototype.js 是怎么做的,我还是贴出来把 prototype.js的代码片段摘取 var $break = new Object(); var $continue = new Object(); var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index ); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result &;amp;&;amp; !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; },
http://www.cnblogs.com/ashun/archive/2006/11/29/function_call_prototype_break_continue_gorush.html
| 感谢原创者的辛勤劳动,希望对您有所帮助,转载请注明原出处。 |
|