当前位置:首页 > 科技  > 软件

小心这个陷阱: 为什么JS中的 Every()对空数组总返回 True

来源: 责编: 时间:2023-09-20 21:55:54 448观看
导读JavaScript 语言的核心部分足够大,以至于我们很容易误解其某些部分的工作方式。最近在重构一些使用 every() 方法的代码时,发现实际上并不理解其背后的逻辑。在我的理解中,我认为回调函数必须被调用并返回true , every()

Ikz28资讯网——每日最新资讯28at.com

JavaScript 语言的核心部分足够大,以至于我们很容易误解其某些部分的工作方式。最近在重构一些使用 every() 方法的代码时,发现实际上并不理解其背后的逻辑。在我的理解中,我认为回调函数必须被调用并返回true , every() 才会返回 true ,但实际上并非如此。对于一个空数组, every() 无论回调函数是什么都会返回 true ,因为那个回调函数从未被调用过。考虑以下情况:Ikz28资讯网——每日最新资讯28at.com

function isNumber(value) {    return typeof value === "number";}[1].every(isNumber);            // true["1"].every(isNumber);          // false[1, 2, 3].every(isNumber);      // true[1, "2", 3].every(isNumber);    // false[].every(isNumber);             // true

在这个例子的每个情况中,对 every() 的调用都会检查数组中的每个项目是否为数字。前四次调用相当直接, every() 产生了预期的结果。现在考虑以下这些例子:Ikz28资讯网——每日最新资讯28at.com

[].every(() => true);           // true[].every(() => false);          // true

这可能更令人惊讶:返回 true 或 false 的回调函数具有相同的结果。这只能发生的唯一原因是如果回调函数没有被调用,而 every() 的默认值是 true 。但是,为什么在没有值来运行回调函数时,空数组会返回 true 给 every() 呢?Ikz28资讯网——每日最新资讯28at.com

要理解为什么,我们需要仔细看看规范是如何描述这个方法的。Ikz28资讯网——每日最新资讯28at.com

实现 every()

ECMA-262 定义了一个 Array.prototype.every()  算法,大致可以翻译成这段JavaScript代码:Ikz28资讯网——每日最新资讯28at.com

Array.prototype.every = function(callbackfn, thisArg) {    const O = this;    const len = O.length;    if (typeof callbackfn !== "function") {        throw new TypeError("Callback isn't callable");    }    let k = 0;    while (k < len) {        const Pk = String(k);        const kPresent = O.hasOwnProperty(Pk);        if (kPresent) {            const kValue = O[Pk];            const testResult = Boolean(callbackfn.call(thisArg, kValue, k, O));            if (testResult === false) {                return false;            }        }        k = k + 1;    }    return true;};

从代码中,你可以看到 every() 假设结果是 true ,并且只有在回调函数对数组中的任何一项返回 false 时才返回 false 。如果数组中没有任何项目,那么就没有机会执行回调函数,因此,该方法无法返回 false 。Ikz28资讯网——每日最新资讯28at.com

现在的问题是:为什么 every() 会表现出这样的行为?Ikz28资讯网——每日最新资讯28at.com

在数学和JavaScript中的“对所有”的量词

MDN页面 提供了为什么 every() 会对空数组返回 true 的答案:Ikz28资讯网——每日最新资讯28at.com

every 的行为就像数学中的“全称量词”。特别是对于空数组,它返回真值。(空集中的所有元素都满足任何给定条件,这是显然的真理。)Ikz28资讯网——每日最新资讯28at.com

空真(Vacuous truth)是一个数学概念,意味着如果给定的条件(称为前件)不能被满足(即给定的条件不为真),那么某件事就是真的。用JavaScript的术语来说,every() 对于一个空集合返回 true,因为没有办法调用回调函数。回调函数代表要测试的条件,如果由于数组中没有值而无法执行它,那么 every() 必须返回 true。Ikz28资讯网——每日最新资讯28at.com

“全称量词”("for all" quantifier)是数学中更大主题“全称量化”(universal quantification)的一部分,它允许你对数据集进行推理。考虑到JavaScript数组在进行数学计算方面的重要性,尤其是在使用类型数组(typed arrays)的情况下,内置支持这样的操作是合理的。而**every()**方法并不是唯一的例子。Ikz28资讯网——每日最新资讯28at.com

在数学和JavaScript中的“存在量词”

JavaScript的 some() 方法实现了存在量化(existential quantification)中的“存在量词”(“存在”有时也被称为“存在”或“对某些”)。这个“存在量词”规定,对于任何空集合,结果都是假的。因此,some() 方法对空集合返回 false,并且也不会执行回调函数。以下是一些相关的示例:Ikz28资讯网——每日最新资讯28at.com

function isNumber(value) {    return typeof value === "number";}[1].some(isNumber);            // true["1"].some(isNumber);          // false[1, 2, 3].some(isNumber);      // true[1, "2", 3].some(isNumber);    // true[].some(isNumber);             // false[].some(() => true);           // false[].some(() => false);          // false

其他语言中的量化

JavaScript并不是唯一实现了集合或可迭代对象的量化方法的编程语言:Ikz28资讯网——每日最新资讯28at.com

  • Python: all() 函数实现了“对所有”  ,而 any() 函数实现了“存在”  。
  • Rust: Iterator::all() 方法实现了“对所有”  ,而 any() 函数实现了“存在” 。

“全称量词”(for all)的 every() 方法的含义与影响

无论你是否认为 every() 方法的行为违反直觉都是可以讨论的。然而,无论你的观点如何,你都需要了解 every() 的“全称量词”(for all)特性以避免错误。简而言之,如果你使用 every() 方法或可能为空的数组,你应该事先进行明确的检查。例如,如果你有一个依赖于数字数组的操作,并且在数组为空时会失败,那么在使用 every() 之前,你应该检查数组是否为空。Ikz28资讯网——每日最新资讯28at.com

function doSomethingWithNumbers(numbers) {    // first check the length    if (numbers.length === 0) {        throw new TypeError("Numbers array is empty; this method requires at least one number.");    }    // now check with every()    if (numbers.every(isNumber)) {        operationRequiringNonEmptyArray(numbers);    }}

再次强调,只有当你有一个数组在为空时不应该被用于操作时,这才重要;否则,你可以避免这个额外的检查。Ikz28资讯网——每日最新资讯28at.com

结论

当我第一次看到 every() 在空数组上的行为时,我感到很惊讶,但一旦你理解了这个操作的更大背景和这个功能在各种语言中的广泛应用,就会觉得它是有道理的。如果你也对这个行为感到困惑,那么我建议你改变阅读 every() 调用的方式。不要把 every() 理解为“这个数组中的每一项是否都符合这个条件?”而应该理解为“这个数组中是否有任何一项不符合这个条件?”这种思维方式的转变可以帮助你避免在未来的JavaScript代码中出现错误。Ikz28资讯网——每日最新资讯28at.com

Ikz28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-10557-0.html小心这个陷阱: 为什么JS中的 Every()对空数组总返回 True

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Spring强大的数据格式化处理功能,你必须得知道

下一篇: Github的一个奇技淫巧,你学会了吗?

标签:
  • 热门焦点
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • 从 Pulsar Client 的原理到它的监控面板

    背景前段时间业务团队偶尔会碰到一些 Pulsar 使用的问题,比如消息阻塞不消费了、生产者消息发送缓慢等各种问题。虽然我们有个监控页面可以根据 topic 维度查看他的发送状态,
  • 之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • 一篇文章带你了解 CSS 属性选择器

    属性选择器对带有指定属性的 HTML 元素设置样式。可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。一、了解属性选择器CSS属性选择器提供了一种简单而
  • 微软邀请 Microsoft 365 商业用户,测试视频编辑器 Clipchamp

    8 月 1 日消息,微软近日宣布即将面向 Microsoft 365 商业用户,开放 Clipchamp 应用,邀请用户通过该应用来编辑视频。微软于 2021 年收购 Clipchamp,随后开始逐步整合到 Microsof
  • Android 14发布:首批适配机型公布

    5月11日消息,谷歌在今天凌晨举行了I/O大会,本次发布会谷歌带来了自家的AI语言模型PaLM 2、谷歌Pixel Fold折叠屏、谷歌Pixel 7a手机,同时发布了Androi
  • 机构称Q2全球智能手机出货量同比下滑11% 苹果份额依旧第2

    7月20日消息,据外媒报道,研究机构的报告显示,由于需求下滑,今年二季度全球智能手机的出货量,同比下滑了11%,三星、苹果等主要厂商的销量,较去年同期均有下
  • 由于成本持续增加,笔记本产品价格预计将明显上涨

    根据知情人士透露,由于材料、物流等成本持续增加,笔记本产品价格预计将在2021年下半年有明显上涨。进入6月下旬以来,全球半导体芯片缺货情况加剧,显卡、处理器
Top