雄辩的Javascript,第7章-尝试抓球

雄辩的Javascript,第7章-尝试抓球,javascript,Javascript,我知道它试图在函数中模拟break语句,我对“try-catch”有一个基本的理解,但我不能理解这个过程 这是你的电话号码 我也不明白代码下面的行- 如果操作函数抛出Break,forEach将吸收异常 停止循环 这是实际的代码- var Break = {toString: function() {return "Break";}}; function forEach(array, action) { try { for (var i = 0; i < array.leng

我知道它试图在函数中模拟break语句,我对“try-catch”有一个基本的理解,但我不能理解这个过程

这是你的电话号码

我也不明白代码下面的行-

如果操作函数抛出Break,forEach将吸收异常 停止循环

这是实际的代码-

var Break = {toString: function() {return "Break";}};

function forEach(array, action) {
  try {
    for (var i = 0; i < array.length; i++)
      action(array[i]);
  }
  catch (exception) {
    if (exception != Break)
      throw exception;
  }
}
var Break={toString:function(){返回“Break”;};
函数forEach(数组、操作){
试一试{
对于(var i=0;i
序言:forEach不是ES5中的版本(我相信这本书早于ES5)。ES5的
Array#forEach
没有提供任何提前中断循环的方法(也就是说,没有代码调用
Array#forEach
看到异常);相反,如果需要提前停止,可以使用
Array#some
Array#every
。这张便条只是为了防止人们感到困惑。下面是关于OP问题中的
forEach
而不是
ES5


在JavaScript中,您可以抛出任何值—一个
错误
对象、任何其他对象、一个数字、一个字符串,等等

他们在那里做的是定义一个特定的对象,
Break
,他们让你用它作为一个例外,告诉
forEach
函数停止在数组中循环

如果迭代函数抛出特定对象
Break
对象,则
forEach
将停止循环,但不会抛出异常。因此,下面的代码不会抛出,而是停在
2

forEach([1, 2, 3, 4], function(entry) {
    console.log(entry);
    if (entry === 2) {
        throw Break;
    }
});
输出:

1 2 1 TypeError: undefined is not a function 1 2 输出:

1 2 1 TypeError: undefined is not a function 1 2 这样做的目的是检查抛出的是否是
Break
对象(尽管这不是一个很好的检查),如果不是,它将重新抛出异常,以便显示给调用
forEach
的代码。但是如果它是
Break
对象,那么它只是默默地停止循环


(这不是一个很好的检查的原因是,如果异常是一个字符串或数字——在JavaScript中,它们可能是——它将做不必要的工作,执行类型强制以尝试查看它是否可以使参数匹配。它实际上应该是
if(exception!==Break)
。)


Tangent(但这可能有助于进一步说明发生了什么):从性能角度来看,这种
forEach
变体的设计并不理想。设置一个
try/catch
块很便宜,但它不是免费的,而抛出一个异常是非常昂贵的。另一种方法是使用迭代器函数的返回值,如下所示:

var Break = {toString: function() {return "Break";}};

function forEach(array, action) {
  for (var i = 0; i < array.length; i++) {
    if (action(array[i]) === Break) {
        return;
    }
  }
}
输出:

1 2 1 TypeError: undefined is not a function 1 2 1. 2. 当然,这需要在每次迭代中对迭代器的返回值进行比较。这样做的成本与设置
try/catch
块非常相似,但在大多数引擎上更便宜

但是,现代发动机真的有速度差吗

对。在我们不打破循环的情况下存在差异,在我们打破循环的情况下存在巨大差异:

在这种情况下,我们不中断循环(我们不
抛出
返回
中断
对象,因此循环完成):

差别相当小,除了Firefox的SpiderMonkey之外,所有引擎都给了
返回
(比较)版本以优势。但是,不管他们走哪条路,成本都是相似的

但以下是我们打破循环的版本:

正如您所看到的,显著地最好是
返回Break比到<代码>抛出断点