欢迎光临

木子屋

标题: JavaScript写作技巧，函数A中调用函数B，怎样在函数B中写代码中断函数A的运行？

作者: dnawo

日期: 2008-07-19 11:15 AM

分类: 脚本语言

内容: 复制内容到剪贴板 程序代码function funcA(){
funcB();
//other code
}
怎么定义函数B，让B在运行的时候不仅能终止B本身，而且能终止函数A的运行？
这是个非常规的问题，我们分两大部分讨论(1.为什么一定这样做 2.怎么实现)
1. 显然，这种编码方式已经打乱了正规的程序编写原则，我们编写函数的目的就是为了封装，为了实现代码的模块化，如果B能让A退出返回, 那这种编码方式肯定比滥用 goto 语句还滥了。
这样做有必要吗?为什么一定要这样做....??
答案如下：
假如我们要扩展Array的prototype，比方说：定义一个find方法，用来返回第一个让执行函数为真的数组元素。
复制内容到剪贴板 程序代码<script>
// by go_rush(阿舜) @ http://ashun.cnblogs.com
Array.prototype.each=function(f){
for(var i=0;i<this.length;i++) f(this[i],i,this)
}
Array.prototype.find=function(f){
var result;
this.each(function(value,index,arr){
if (f(value,index,arr)) result=value
})
return result
}
var arr=[1,2,3,4,5,7,9]
function foo(v){ //检测是不是偶数
return v%2==0
}
alert(arr.find(foo))
</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){}
复制内容到剪贴板 程序代码<script>
// by go_rush(阿舜) @ http://ashun.cnblogs.com
var =new Object()
Array.prototype.each=function(f){
try{
for(var i=0;i<this.length;i++){
try{
f(this[i],i,this)
}catch(e){
if (e==) throw e
}
}
}catch(e){}
}
Array.prototype.find=function(f){
var result;
this.each(function(value,index,arr){
if (f(value,index,arr)){
result=value
throw
}
})
return result
}
var arr=[1,2,3,4,5,7,9]
function foo(v){ //检测是不是偶数
return v%2==0
}
alert(arr.find(foo))
</script>
在第24行，如果程序已经找到第一个满足函数返回值为真的元素，那么就抛出一个自定义异常，终止 this.each()的运行.. 注意第12行，只有确保函数抛出的是自定义异常才继续向上抛出异常，从而终止函数的运行。
在上面的代码中，我用的 try---catch 方法完全是用来解决本贴所提出的问题的，并未进行任何其他错误处理。
在这方面，prototype.js 通过定义两个自定义异常对象 和 ，既照顾到了异常处理，又解决了本贴提出的问题。
Enumerable 对象实现得很优雅，大家不妨再去体会体会 prototype.js 中Enumerable的妙处。
我们看看prototype.js 是怎么做的，我还是贴出来吧
prototype.js的代码片段摘取：
复制内容到剪贴板 程序代码var = new Object();
var = new Object();
var Enumerable = {
each: function(iterator) {
var index = 0;
try {
this._each(function(value) {
try {
iterator(value, index++);
} catch (e) {
if (e != ) throw e;
}
});
} catch (e) {
if (e != ) throw e;
}
},
all: function(iterator) {
var result = true;
this.each(function(value, index) {
result = result && !!(iterator || Prototype.K)(value, index);
if (!result) throw ;
});
return result;
},
any: function(iterator) {
var result = true;
this.each(function(value, index) {
if (result = !!(iterator || Prototype.K)(value, index))
throw ;
});
return result;
},

+ 查看当前日志评论 (0)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.930 ms

返回

标题: JavaScript写作技巧，函数A中调用函数B，怎样在函数B中写代码中断函数A的运行？

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.930 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.965 ms

返回