【问题标题】:What is “assert” in JavaScript?JavaScript 中的“断言”是什么?
【发布时间】:2013-02-25 03:27:20
【问题描述】:

assert 在 JavaScript 中是什么意思?

我见过类似的东西:

assert(function1() && function2() && function3(), "some text");

并且想知道assert()的方法是做什么的。

【问题讨论】:

    标签: javascript assert


    【解决方案1】:

    JavaScript 本身没有标准的assert。也许您正在使用一些提供的库;例如,如果您使用的是 Node.js,也许您使用的是 assertion module。 (提供实现Console API 的控制台的浏览器和其他环境提供console.assert。)

    assert 函数的通常含义是如果传递给函数的表达式为假则抛出错误;这是assertion checking 的一般概念的一部分。通常断言(它们被称为)仅用于“测试”或“调试”构建并从生产代码中剥离。

    假设您有一个应该始终接受字符串的函数。您想知道是否有人用不是字符串的东西调用了该函数(没有像 TypeScript 或 Flow 这样的类型检查层)。所以你可以这样做:

    assert(typeof argumentName === "string");
    

    ...如果条件为假,assert 会抛出错误。

    一个非常简单的版本如下所示:

    function assert(condition, message) {
        if (!condition) {
            throw message || "Assertion failed";
        }
    }
    

    更好的是,利用Error 对象,它具有收集堆栈跟踪等优点:

    function assert(condition, message) {
        if (!condition) {
            throw new Error(message || "Assertion failed");
        }
    }
    

    【讨论】:

    • ...对 JS 中的类型感到自满?我认为这是assert 最糟糕的原因之一。
    • @cHao:有有效的用例。这只是我想到的第一个例子。例子不是重点。断言的概念是重点。
    • 我在if(!condition) 中添加到我的代码中的东西是设置var throwError=true; 然后debugger; 然后将抛出部分包装在if(throwError) 中。这样,如果我打开调试器,它就会中断,如果我愿意,我可以将 throwError 设置为 false,然后在退出时检查所有范围。
    • @Rick 如果您使用 Chrome DevTools,您可以简单地在 Sources 选项卡中启用“Pause on Uncaught Exceptions”,它会在throw 处自动中断。这样你就不需要debugger; 语句。请参阅developer.chrome.com/devtools/docs/… 了解更多信息。
    • @machineghost:我不明白这有多“简单”,您刚刚将if 换成了条件运算符。无论如何,在当今世界,我不会费心支持没有Error 的引擎。
    【解决方案2】:

    如果使用现代浏览器或nodejs,可以使用console.assert(expression, object)

    更多信息:

    【讨论】:

    • 仅供参考,这更像console.error,因为代码会继续执行。
    • @DanielSokolowski,没错。 console.assert 不太好,除非它具有与 throw 相同的行为。
    • console.assert 之后继续执行的原因是断言不是错误处理函数。它们仅用于开发期间的代码正确性检查。传统上,它们在生产环境中被完全禁用,以避免实时系统因为一些琐碎的事情而终止。浏览器被视为生产环境,因此console.assert 不会在那里终止执行。如果您依赖断言来停止执行,那么您应该使用适当的错误处理,因为这不是断言的用途。
    • @RonBurk:语言设计者决定了“断言的用途”。在C++ 中,[an assertion] 旨在捕获编程错误,而不是用户或运行时错误,因为它通常在程序退出其调试阶段后被禁用。 PHP根据经验,如果没有激活断言检查,您的代码应该始终能够正常工作。 被动语态并不是要授权个人偏好,而是报告被广泛接受的一般做法。
    • @Don:点了,但我只是引用链接页面。我确实相信断言应该被视为可以被禁用,即使只是因为有一天你的代码可能会被认为这样做是安全的人使用。如果断言对您的代码至关重要,那么我认为它们确实应该升级为正确的错误检查,而不是依赖于并不总是保证终止执行的调试方法。更不用说让你的代码在生产环境中反复死掉,而它可能只会返回错误并继续,这可能会导致比它值得的压力更大!
    【解决方案3】:

    其他答案很好:ECMAScript5 中没有内置断言函数(例如,基本上可以在任何地方使用的 JavaScript),但有些浏览器会将它提供给您,或者具有提供该功能的附加组件。虽然最好为此使用完善/流行/维护的库,但出于学术目的,“穷人的断言”函数可能看起来像这样:

    const assert = function(condition, message) {
        if (!condition)
            throw Error('Assert failed: ' + (message || ''));
    };
    
    assert(1 === 1); // Executes without problem
    assert(false, 'Expected true');
    // Yields 'Error: Assert failed: Expected true' in console
    

    【讨论】:

    • 顺便说一句,人们可以轻松地对其进行修改,使其仅在开发环境中引发错误(例如,通过包装另一个 if / 添加另一个条件),否则什么也不做或只打印一个警告。就个人而言,我的观点是断言应该只在测试代码中(例如检查预期和实际结果是否匹配);在生产代码中,它们要么是多余的(保证设计正确)并因此被删除,要么仅用于保护用户/外部输入,在这种情况下,它们可以通过清理逻辑和标准异常处理来替换(例如trycatch、@ 987654326@)
    • @jacobq 这不适用于assert。 Assert 是一种合同,旨在通过程序设计永远不会是错误的。除非在测试中捕获断言是错误的。这是可以捕获断言的唯一原因。您不能断言用户或客户端输入。将程序错误归咎于攻击者是没有意义的。即使是异常也会很糟糕,因为用户输入不是异常情况,而不是错误。这就像将程序错误归咎于用户/客户端。该原则与语言无关。只能怪处理不当或消毒不当。
    • @ChrisoLosoph 你能澄清一下你认为不合适的地方吗?请注意,此实现是“poor man's assert”,即一个近似值,我并不是说应该使用 assert 来代替异常处理或逻辑。我确实提到过,如果它们被用于保护输入之类的事情,那么还有其他可能更合适的替代方案(例如 if/else 逻辑或 try/catch 异常处理)。
    • 我很抱歉造成混乱。我指的不是你的回答,而是你之前评论的最后一句话:-)。
    【解决方案4】:

    assert() 不是原生 javascript 函数。这是某人制作的自定义功能。您将不得不在您的页面或文件中查找它并将其发布给任何人以帮助确定它在做什么。

    【讨论】:

      【解决方案5】:

      检查这个:http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-quick-and-easy-javascript-testing-with-assert/

      它用于测试 JavaScript。令人惊讶的是,这段代码只有五六行,在测试时提供了强大的功能和对代码的控制。

      assert 函数接受两个参数:

      结果:一个布尔值,表示您的测试是通过还是失败

      description:对您的测试的简短描述。

      assert 函数然后简单地创建一个列表项,应用“通过”或“失败”类别,具体取决于您的测试返回的是真还是假,然后将描述附加到列表项。最后,将该代码块添加到页面中。这非常简单,但效果很好。

      【讨论】:

        【解决方案6】:

        如果断言为假,则显示消息。具体来说,如果第一个参数为 false,则第二个参数(字符串消息)将记录在开发人员工具控制台中。如果第一个参数为真,则基本上什么都不会发生。一个简单的例子——我使用的是谷歌开发者工具:

        var isTrue = true;
        var isFalse = false;
        console.assert(isTrue, 'Equals true so will NOT log to the console.');
        console.assert(isFalse, 'Equals false so WILL log to the console.');
        

        【讨论】:

          【解决方案7】:

          它可能带有您的某些代码正在使用的测试库。这是其中的一个示例(可能与您的代码使用的库不同,但它显示了总体思路):

          http://chaijs.com/guide/styles/#assert

          【讨论】:

            【解决方案8】:

            单词或函数“assert”主要用于测试应用程序的部分。

            断言函数是指示程序检查条件(也称为“断言”)的一种简短方法,如果条件不为真,则会抛出错误。

            让我们看看它在“普通代码”中的样子

            if (typeof "string" === "array") { throw Error('Error: "string" !== "array"'); }

            使用assert,您可以简单地写:

            assert(typeof "string" === "array")

            在 Javascript 中,没有原生的 assert 函数,所以你必须使用某个库中的一个。

            简单介绍可以查看这篇文章:

            http://fredkschott.com/post/2014/05/nodejs-testing-essentials/

            希望对你有帮助。

            【讨论】:

              【解决方案9】:

              如果第一个属性为假,则断言抛出错误消息,第二个属性是要抛出的消息。

              console.assert(condition,message);
              

              很多 cmets 说 JavaScript 中不存在断言,但 console.assert() 是 JavaScript 中的断言函数 断言的想法是找出错误发生的原因/位置。

              console.assert(document.getElementById("title"), "You have no element with ID 'title'");
              console.assert(document.getElementById("image"), "You have no element with ID 'image'");
              

              根据消息,您可以在此处找到错误所在。 这些错误消息将以红色显示到控制台,就好像我们调用了console.error();

              您可以使用断言来测试您的功能,例如:

              console.assert(myAddFunction(5,8)===(5+8),"Failed on 5 and 8");
              

              注意条件可以是!=<>

              这通常用于通过提供一些测试用例来测试新创建的函数是否按预期工作,而不是用于生产。

              要在控制台中查看更多功能,请执行console.log(console);

              【讨论】:

                【解决方案10】:

                Java 有一个assert 语句,JVM 默认禁用断言验证。它们必须使用命令行参数-enableassertions(或其简写-ea)显式启用,

                虽然 JavaScript 支持 console.assert(),但它只是一种日志记录方法,如果断言失败不会中断当前过程。

                为了把东西放在一起并满足各种需求,这里有一个很小的 ​​js 断言库。

                globalThis.assert = (()=> {
                  class AssertionError extends Error {
                    constructor(message) {
                      super(message);
                      this.name = 'AssertionError';
                    }
                  }
                  let config = {
                    async: true,
                    silent: false
                  };
                  function assert(condition, message = undefined) {
                    if (!condition) {
                      if (config.silent) {
                        //NOOP
                      } else if (config.async) {
                        console.assert(condition, message || 'assert');
                      } else {
                        throw new AssertionError(message || 'assertion failed');
                      }
                    }
                  }
                  assert.config = config;
                  return assert;
                })();
                
                
                /* global assert */
                Object.assign(assert.config, {
                  // silent: true, // to disable assertion validation
                  async: false, // to validate assertion synchronously (will interrupt if assertion failed, like Java's)
                });
                
                let items = [
                  {id: 1},
                  {id: 2},
                  {id: 3}
                ];
                function deleteItem(item) {
                  let index = items.findIndex((e)=> e.id === item.id);
                  assert(index > -1, `index should be >=0, the item(id=${item.id}) to be deleted doesn't exist, or was already deleted`);
                  items.splice(index, 1);
                }
                
                console.log('begin');
                deleteItem({id: 1});
                deleteItem({id: 1});
                console.log('end');

                【讨论】:

                  【解决方案11】:

                  可以在性能和兼容性方面改进以前的答案。

                  检查一次如果Error对象存在,如果不声明它:

                  if (typeof Error === "undefined") {
                      Error = function(message) {
                          this.message = message;
                      };
                      Error.prototype.message = "";
                  }
                  

                  然后,每个断言都会检查条件,并总是抛出一个Error对象

                  function assert(condition, message) {
                      if (!condition) throw new Error(message || "Assertion failed");
                  }
                  

                  记住,控制台不会显示真正的错误行号,而是assert函数的行,对调试没有用处。

                  【讨论】:

                    【解决方案12】:

                    如果你使用 webpack,你可以使用node.js assertion library。虽然他们声称它“不打算成为一个通用的断言库”,但对于临时断言来说似乎已经足够了,而且在 Node 空间中似乎不存在任何竞争对手(Chai 是为单元测试而设计的)。

                    const assert = require('assert');
                    ...
                    assert(jqXHR.status == 201, "create response should be 201");
                    

                    您需要使用 webpack 或 browserify 才能使用它,因此显然这仅在您的工作流程中已经存在时才有用。

                    【讨论】:

                      【解决方案13】:

                      除了console.assertrolling your own 等其他选项外,您还可以使用invariant。它有几个独特的功能:

                      • 它支持格式化的错误消息(使用%s 说明符)。
                      • 在生产环境中(由 Node.js 或 Webpack 环境确定),错误消息是可选的,允许(稍微)更小的 .js。

                      【讨论】:

                        【解决方案14】:

                        正如 T.J. 所说,JavaScript 中没有 assert。 但是,有一个名为assert的节点模块,即used mostly for testing。因此,您可能会看到如下代码:

                        const assert = require('assert');
                        assert(5 > 7);
                        

                        【讨论】:

                          【解决方案15】:

                          Node.js 实际上有一个可以导入的assert 函数。

                          const assert = require('assert')

                          它的工作方式与预期完全一样,assert(false) 会引发错误,assert(false, message) 会引发错误并显示消息。

                          其他答案已经指出 JS 本身没有原生断言函数,并且在撰写本文时(2021 年 4 月)仍然如此。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2010-12-06
                            • 2017-12-12
                            • 2014-07-06
                            • 1970-01-01
                            • 2010-10-08
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多