【问题标题】:This mergesort should "of" failed, right?这个合并排序应该“的”失败,对吧?
【发布时间】:2015-08-10 20:39:18
【问题描述】:

我在查看 this mergesort implementation on Code Review 时发现了一些奇怪的东西……

/************************************************************
 * Mergesort implementation
 ***********************************************************/

function sort(array) {
  var len = array.length;
  var middle = Math.floor(len*0.5);
  var left = array.slice(0,middle);
  var right = array.slice(middle, len);

  if (len == 1) {
    return array;
  } else {

  }

  return merge(sort(left), sort(right));
}


function merge(left, right) {
  var a = left.length;
  var b = right.length;


  if (a > 0 && b > 0) {
    if (left[0] > right[0]) {
      return [].concat(left[0], merge(left.slice(1,a), right));
    } else {
      return [].concat(right[0], merge(right.slice(1,b), left));
    }
  } else if (a == 0) {
    return right;
  } else of (b == 0)
    return left;

}


/************************************************************
 * Demonstration
 ***********************************************************/

function doSort() {
    var array = document.getElementById('in').value.split(/[, ]+/).map(function(e) {
        return parseInt(e);
    });
    var sorted = sort(array);
    document.getElementById('out').value = sorted;
}

function generateRandom(len) {
    var array = [];
    for (var i = 0; i < len; i++) {
        array.push(Math.round(Math.random() * 100));
    }
    document.getElementById('in').value = array;
};

generateRandom(20);
<button onclick="generateRandom(20)">⬇︎ Generate random numbers ⬇︎</button>
<div><input id="in" size="80"></div>
<button onclick="doSort()">⬇︎ Sort ⬇︎</button>
<div><input id="out" size="80" disabled></div>

最后一个条件分支是 else of 而不是 else if。通常,else of 会导致语法错误。然而,无论我怎么努力,我都无法触发语法错误——它总是成功返回一个按降序排序的数组!

我知道,else of (b == 0) 可以直接替换为 else,但我仍然想知道:这段代码怎么可能工作?

【问题讨论】:

  • 代码对我不起作用。
  • 在铬上工作得很好......

标签: javascript if-statement keyword mergesort


【解决方案1】:

这是因为 Javascript 的两个“坏事”的组合:在仅包含单个语句的块语句中跳过大括号,以及 semicolon insertion

您的 if 语句,正确支撑,应该如下所示:

if (a > 0 && b > 0) {
    if (left[0] > right[0]) {
        return [].concat(left[0], merge(left.slice(1,a), right));
    } else {
        return [].concat(right[0], merge(right.slice(1,b), left));
    }
} else if (a == 0) {
    return right;
} else of (b == 0) {
    return left;
}

但是,由于缺少大括号和分号插入,Javascript 会像这样查看/解析它:

if (a > 0 && b > 0) {
    if (left[0] > right[0]) {
        return [].concat(left[0], merge(left.slice(1,a), right));
    } else {
        return [].concat(right[0], merge(right.slice(1,b), left));
    }
} else if (a == 0) {
    return right;
} else {
    of(b == 0);
}

return left;

如果你总是传入合法的leftright 数组,那么最后一个else 分支永远不会到达,因此你没有看到异常。

如果传入一个空的right数组,它将到达最后一个分支并抛出of is not a function

merge([10, 20, 30], []);

任何受人尊敬的编码标准都应该明确要求永远不要使用 Javascript 的这两个“特性”……但这只是一种意见。

【讨论】:

  • else of 部分不等于else { of (b == 0) } return left; 吗?
  • 如果有的话,那就是else ( of (b == 0) ) { return left; }
  • else 不接受“参数”.. 但括号不仅仅是在 Javascript 中定义参数列表。
  • 我很怀疑。函数中没有for 循环。如果我只是尝试评估of (b == 0),我会得到ReferenceError: Can't find variable: of。如果我定义了一个名为of 的函数,那么它将of (b == 0) 视为函数调用。
  • @200_success 是的,它真的很有趣。我发现它始终会产生错误IF实际到达了有问题的分支,但否则无法生成错误。
【解决方案2】:

of 是 ES6 中的关键字,用于迭代对象。 但在这种情况下,of 的行为是函数而不是关键字..

函数代码永远不会去else of (b == 0) return left;部分..所以编译器不会抛出ReferenceError: of is not defined

如果您将 of 关键字更改为另一个词,例如 else often(b==0)....,那么代码也可以工作

当您发送右侧为空时,代码将抛出错误ReferenceError: of is not defined,所以最后这只是错字。

【讨论】:

    猜你喜欢
    • 2020-11-26
    • 1970-01-01
    • 2021-12-09
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多