博客园 :: 首页 ::  ::  ::  :: 管理

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],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],i,this)) return this[i]
 }
}

这样不整个世界都清净了吗.

是的,如果我只是简单的写一个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){}

实现代码

在第24行,如果程序已经找到第一个满足函数返回值为真的元素,那么就抛出一个自定义异常,终止 this.each()的
运行..   注意第12行,只有确保函数抛出的是自定义异常才继续向上抛出异常,从而终止函数的运行.

在上面的代码中,我用的 try---catch方法完全是用来解决本贴所提出的问题的,并未进行任何其他错误处理.

在这方面,prototype.js ,通过定义两个自定义异常对象 $break 和 $continue ,既照顾到了异常处理,又解决了本贴
提出的问题. Enumerable 对象实现得很优雅, 大家不妨再去体会体会 prototype.js 中Enumerable的妙处.

我们看看prototype.js 是怎么做的,我还是贴出来把

prototype.js的代码片段摘取


 

Feedback

#1楼   回复  引用    

2006-11-29 08:23 by Bao*3[未注册用户]
能达到目的就可以, 不过也许自己定义个exception会更好

#2楼   回复  引用    

2006-11-29 08:58 by 布尔[匿名][未注册用户]
阅读代码的快乐

#3楼   回复  引用    

2006-11-29 09:16 by yzx110[匿名][未注册用户]
自定义异常,然后抛出,可能每个使用each的地方还要try{}catch(e){}
感觉还不如循环判断的好

封装本来就是封装变化的地方,一个循环很稳定,写很多地方除了麻烦点没什么。并且each就不是干这个事情的,而非让它干这个事情,别扭。

并且相对于阅读代码的人理解循环比理解异常中断要简单的多

#4楼   回复  引用  查看    

2006-11-29 09:18 by qqhe325      
在each里面加个break;
Array.prototype.each=function(f){
for(var i=0;i<this.length;i++) if(f(this[i],i,this)==true) break;//,i,this
}

Array.prototype.find=function(){
var result;
this.each(function(value,index,arr){//
//if (f(value,index,arr)) result=value
//alert(value);
if (foo(value,index,arr)==true)
{
//alert(value);
result=value;
return true;

}



})
return result;
}

var arr=[1,2,3,4,5,7,9];

function foo(v){ //检测是不是偶数
if(v%2==0)return true;
}
alert(arr.find(foo))

#5楼[楼主]   回复  引用  查看    

2006-11-29 09:23 by Go_Rush      
@qqhe325
你这个方法是只钟对本问题而提出的,如果我现在要定义一个方法,查找
非偶数,那你的each岂不又要改

#6楼[楼主]   回复  引用  查看    

2006-11-29 09:27 by Go_Rush      
@yzx110[匿名]
我始终觉得,还是用异常要好,当然代码的可读性降低不少。
原因如下:
1.因为each就是遍历所有数组元素,就是干这个事情的阿,如果每个
方法都用循环来遍历,那就是都重复干each干的活了
2.如果用each,所有的方法有了一个统一的入口,以后要修改遍历方法
的时候,只需要改动 each就可以了

#7楼[楼主]   回复  引用  查看    

2006-11-29 09:28 by Go_Rush      
@布尔[匿名] && Bao*3

谢谢支持,请多关注本博客

#8楼   回复  引用    

2006-11-29 10:15 by yzx110[匿名][未注册用户]
@Go_Rush

我倒是认为
each是不是干查找某个元素或者某些元素的事啊,这样还不如专门写个find做
感觉把each和find混了

#9楼   回复  引用  查看    

2006-11-29 10:47 by lixiong      
传说中的通过异常来控制程序执行的牛人又出现了

#10楼[楼主]   回复  引用  查看    

2006-11-29 12:42 by Go_Rush      
@lixiong
呵呵,我也反对这样做的。不过在一些特殊场合,适当的用一下还是可以的。
这东西要是用多了,不该用的地方滥用的话,会出乱子的

#11楼[楼主]   回复  引用  查看    

2006-11-29 12:44 by Go_Rush      
@yzx110[匿名]
是啊,你的那种方法也是很好。逻辑很清晰,但是我想本贴的那种程序环境,还是用异常好。 each() 只负责遍历, find()才实现业务逻辑

#12楼   回复  引用    

2006-11-29 13:17 by 木野狐[匿名]
感觉这个做法有点为精简代码而精简了,没有必要。
实际上回头看一下客户代码必须用 try..catch 反而不方便了。

#13楼   回复  引用    

2006-11-29 16:42 by 姓名[未注册用户]
检查B函数的返回值

#14楼   回复  引用    

2007-04-18 13:49 by sASs[未注册用户]
saSsASsSs



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 575854




相关文章:

相关链接: