【问题标题】:Why 'Unexpected "."' when using || operator for a default value in parenthesis为什么使用 || 时出现“意外的“。”括号中的默认值运算符
【发布时间】:2016-01-18 01:21:18
【问题描述】:

出乎意料的“。”来自 jslint (http://jslint.com/) 的代码:

function test(foo) {
    "use strict";
    return (foo || "").replace("bar", "baz");
}

为什么jslint的||有问题运算符强制一个空字符串,以便可以在不导致错误的情况下执行替换,以防 foo 作为未定义传入?

通过了:

function test(foo) {
    "use strict";
    var xFoo = (foo || "");
    return xFoo.replace("bar", "baz");
}

我知道它是基于意见的,我可以忽略它,等等......但试图理解为什么这样的链接不受欢迎。也知道 eshint,但我不想绕过这个消息,只是想了解原因。

似乎第一种方法更简洁明了,因为它不需要额外的变量 (xFoo)。

这两个函数在所有条件下都做同样的事情。

【问题讨论】:

  • 这看起来像是 JSLint 中的一个错误。
  • idk 具体为什么 jslint 有问题但它不是好的代码。如果您将true1 传递给它,您将遇到问题。
  • @ChrisGciso - 如果您知道foo 将是错误的或字符串,那么您拥有的代码绝对没有问题。这不是语法错误。如果您对foo 的可能值有所了解,或者如果您希望它在传递了无效的foo 时抛出异常,这甚至不是编程错误。因此,在许多情况下,使用已接受答案中的代码只是一种使警告消失的方法,而不是修复任何实际错误的方法。
  • @ChrisGciso - 所以,JSLint 迫使您处理一些可能是非常好的代码,而 JSHint 显然认为它认为不值得抱怨。两者都不是真正的对或错——这些都是意见。当一个人知道如果/当为foo 传递了一个无效值或者是否会发生这种情况时,你希望函数如何表现,唯一真正的对与错就出现了。
  • @ChrisGciso fwiw, "JSLint 获取一个 JavaScript 源并对其进行扫描。如果它发现问题,它会返回一条描述问题的消息以及源中的大致位置。问题不是必然是语法错误,尽管它经常是。JSLint 会查看一些样式约定以及结构问题。它并不能证明您的程序是正确的。它只是提供了另一组眼睛来帮助发现问题。JSLint 定义了 ..,一个比 ECMAScript 定义的语言更严格。JSLint 将拒绝大多数合法程序。" jslint.com/help.html

标签: javascript jslint


【解决方案1】:

使用String() contructor 删除 jslint 的错误

function test(foo) {
    "use strict";
    return String(foo || "").replace("bar", "baz");
}

另请参阅Distinction between string primitives and String objectsJSLint Help

【讨论】:

  • @ChrisGciso 这也通过了return foo && foo.replace("bar", "baz");
  • @ChrisGciso Appear 附加到字符串文字的方法在 jslint 通知为警告? function test(foo) { "use strict"; if (!foo) { return "".replace("bar", "baz"); } } , function test(foo) { "use strict"; if (!foo) { return "bar".replace("bar", "baz"); } }
  • @ChrisGciso - 我不会说这是“正确”的编码方式。这是让 jsLint 停止抱怨的方法。 jsLint 在这里不是上帝。如果有人将true 传递给它,我可能会编写这样的函数并希望它抛出异常,因为这是一个我不想强制转换为字符串的无效值。那么,这种新方法是错误的。
  • 这个答案没有意义。它讨论了字符串对象和 String 构造函数,但在给定的代码中都没有使用。
  • 这不是阻止 jsLint 抱怨的正确方法,它只是让它停止抱怨的方法之一。这与String 函数完全无关;这都是关于函数调用的——Number(foo || "").replace(…) 也一样。
【解决方案2】:

这可能是因为它认为(foo || "") 将评估为布尔表达式,所以像false.replace() 这样的东西没有意义。即使,是的,在您的情况下,您会得到一个变量或空字符串。

【讨论】:

  • 它永远不会是false,但它可能是true
  • 我并不是说它会评估为布尔值,只是 JSLint 可能认为它会,因为它看起来像一个布尔表达式。此外,如果foofalseundefined 等,则表达式将使用"",这也是错误的。如果这两种情况都可以评估为false,那它怎么可能是true
【解决方案3】:

你可以只写两行。

function test(foo) {
    "use strict";
    foo = foo || "";
    return foo.replace("bar", "baz");
}

无需创建临时的xFoo 变量。 foo 参数是自 JavaScript does not support passing-by-reference 以来传入的参数的副本。

看起来您在这里尝试做的是提供一个默认参数。在这种情况下,我会通过更加明确并对其进行类型检查来明确您在做什么:

function test(foo) {
    "use strict";
    if (foo === undefined) {
      foo = "";
    }
    return foo.replace("bar", "baz");
}

是的,它不那么简洁,但它会减少代码意图被稍后阅读它的人误解的空间。显式检查类型还可以让您处理其他潜在问题。

function test(foo) {
    "use strict";
    if (foo === undefined) {
      foo = "";
    } else if (typeof foo !== 'string') {
      throw('foo must be a string');
    }
    return foo.replace("bar", "baz");
}

如果你使用的是 ES2015,你也可以使用 default parameter:

function test(foo = "") {
    "use strict";
    if (typeof foo !== 'string') {
      throw('foo must be a string');
    }
    return foo.replace("bar", "baz");
}

对于几乎所有项目,我建议将Babel 添加到您的构建过程中,以便您可以使用默认参数和many other ES2015 添加到语言中的有用功能。使用 Babel 可以让你现在就可以使用它们,而不必等待所有浏览器都实现它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 2022-01-16
    • 2021-05-25
    • 1970-01-01
    • 2012-02-12
    • 2018-05-08
    • 1970-01-01
    相关资源
    最近更新 更多