记录--JavaScript 令人惊讶的一点:对于空数组every()方法返回true

这篇具有很好参考价值的文章主要介绍了记录--JavaScript 令人惊讶的一点:对于空数组every()方法返回true。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--JavaScript 令人惊讶的一点:对于空数组every()方法返回true

JavaScript 语言的内核足够大,导致我们很容易误解它的某些部分是如何工作的。我最近重构了一些使用 every ()方法的代码,并且发现我并不真正理解every()的逻辑。在我看来,我认为回调函数必须被调用并返回 true的时候every() 才能返回 true,但事实并非如此。但是对于空数组,不管回调函数是什么,every ()都返回 true,因为根本不会调用该回调函数。看一下例子:
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(() => true);           // true
[].every(() => false);          // true

这样的结果可能更令人感到惊讶: 对于every(),返回 true 或 false 的回调都具有相同的结果。发生这种情况的唯一原因是调用回调函数没有被调用,并且 every ()的默认返回值为 true。但是,当没有值可以用来运行回调函数时,为什么空数组对 every ()返回 true呢?

为了理解其中的原因,重要的是看看规范是如何描述这种方法的。

实现every()方法

ECMA-262定义了一个 Array.Prototype.every ()算法,该算法大致可以翻译成这段 JavaScript 代码:

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。

现在的问题是:为什么every()要这样做?

数学和 JavaScript 中的全称量词

译者注:全称量词是指“所有”的概念,常用符号为∀。例如,对于集合S中的元素x,可以表示为∀x∈S,意为“对于S中的每一个元素x都成立”

MDN 提供了为什么 every ()对于空数组返回 true 的答案:

every 和数学中的全称量词"任意(∀)"类似。特别的,对于空数组,它只返回 true。
(这种情况属于无条件正确,因为空集的所有元素都符合给定的条件。)

无条件正确是一个数学概念,它意味着如果一个给定的条件(称为先行条件)不能被满足(也就是说,给定的条件是不真实的) ,那么某些东西就是真的。要将其应用到 JavaScript 中,那就是every ()对于空数组返回 true,因为没有办法调用回调函数 。回调代表了要测试的条件,如果由于数组中没有值而无法执行,那么 every ()必须返回 true。

全称量词是数学中一个更大的主题的一部分,这个主题被称为“全称量化”,它允许你对数据集进行推理。考虑到 JavaScript 数组对于执行数学计算的重要性,特别是对于类型化数组,内置支持这种操作是有意义的。要知道,every()并不是唯一的例子。

数学和 JavaScript 中的存在量词

译者注: 存在量词是指“存在”的概念,常用符号为∃。例如,对于集合S中的元素x,可以表示为∃x∈S,意为“存在S中的一个元素x”

JavaScript 的some()方法实现了存在量词。“存在”量词指出,对于任何空集,结果都是 false。因此,some ()方法对于空数组返回 false,并且也不执行回调函数。下面是一些例子:

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 并不是唯一的一种为集合或可迭代对象实现了量词相关方法的编程语言:

Python: all ()函数实现全称量词,而 any ()函数实现了存在量词。

Rust: Iterator: : all ()函数实现了全称量词,而 any ()函数实现了存在量词。

因此,JavaScript 与 every ()和 some ()都有着良好的合作关系。

意味着全称量词的every()

你是否认为evey()的行为是违反直觉的?这可有待商榷。然而,不管您的观点如何,您都需要了every()所具有的全程量词的性质以避免错误。简而言之,如果可能为空的数组使用了every (),则应该事先添加一个显式检查。例如,如果您有一个依赖于数字数组的操作,并且该操作将以空数组失败,那么您应该在使用 every ()之前检查该数组是否为空:

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);
    }
}

注意,只有当数组为空时不能执行某操作时,这样做是有必须要的。否则,可以避免这种额外的检查。

总结

虽然我对空数组上执行 every ()方法的执行结果感到惊讶,可是当我了解了某个操作的更大范围的上下文以及这种功能在各种语言之间的表现时,我就会感到释然。如果您也对这种行为感到困惑,那么我建议您在遇到every()的调用时改变你对它的理解。不再将 every ()读作“此数组中的每个项是否匹配此条件?”而是读作“数组中有没有不符合条件的项?”这种思维上的转变可以帮助您在以后的 JavaScript 代码中避免错误。

本文转载于:

https://juejin.cn/post/7279093851000062010

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--JavaScript 令人惊讶的一点:对于空数组every()方法返回true文章来源地址https://www.toymoban.com/news/detail-709889.html

到了这里,关于记录--JavaScript 令人惊讶的一点:对于空数组every()方法返回true的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 给想考CISP的一点建议

    了解CISP考试: 在报名参加考试之前,要充分了解CISP认证考试的考试内容、考试形式、考试难度等相关信息,这有助于你制定更有效的备考计划。 制定备考计划: 根据自己的实际情况和考试要求,制定一份详细的备考计划,包括学习时间、学习内容、练习测试等。在备考期

    2024年02月01日
    浏览(38)
  • 找实习、工作的一点浅见

    一、实习的必要性。 为什么需要去实习?1、实习能帮助自己增进对于具体职场的认识,包括具体工作的职责、内容、工作氛围、是否有较大压力等等;2、通过一段时间的实习经历,能帮助自己作出未来是否能胜任类似的工作的判断,如果有留用,是否考虑留下,如果没有留

    2024年02月10日
    浏览(52)
  • 对单片机的一点理解

    前言 大一时学过一段时间的51单片机,后面就一直研究STM32和算法,最近工作搞51单片机有半年了,有一些自己的想法,跟公司的工程师也探讨了一些,结合聊天记录,写了这篇博客,希望对读者有帮助。 有纰漏请指出,转载请说明。 学习交流请发邮件 1280253714@qq.com 对单片机

    2024年04月14日
    浏览(60)
  • [RPC]关于RPC的一点理解

    以下内容仅为个人理解,不作正确性保证,感谢批评指正 在分布式计算中,远程过程调用 (RPC) 是指计算机程序导致过程(子例程)在不同的地址空间(通常在共享网络上的另一台计算机上)中执行, 它的编码就好像是普通(本地)过程调用一样,程序员没有 显式 编码远程

    2024年02月10日
    浏览(37)
  • 对卷积的一点具象化理解

            卷积的公式一般被表示为下式:         对新手来说完全看不懂这是干什么,这个问题需要结合卷积的应用场景来说。         卷积比较广泛的应用是在信号与系统中,所以有些 公式的定义会按照信息流的习惯 。假设存在一串信号 g(x) 经过一个响应 h(x)

    2024年02月09日
    浏览(34)
  • Hyperledger Fabric 网络环境的一点理解

    Hyperledger Fabric 开发链码,一般都是测试网络开发,然后部署到生产网络。 下面介绍测试网络、生产网络的一点理解。 使用cryptogen等工具建立测试网络,开发环境使用。 这里以https://github.com/hyperledger/fabric-samples 2022.2.12的代码为例进行说明。 目录: fabric-samples/test-network/orga

    2024年02月15日
    浏览(37)
  • Solidity合约中签名验证的一点实践

    在目前NFT概念国内外火爆的背景下,涌现了很多项目,特别是公链以太坊上,社区与新团队更是层出不穷,让人眼花缭乱。 而一个新项目上线的成功与否,往往与其社区支持力度息息相关。现在很多新项目方为了拥有更多的热度,人为的设置了白名单这个玩法和门槛,于是我

    2024年02月08日
    浏览(42)
  • 对KMP算法的一点碎碎念——上篇

    假设有模式串T为: a b a b a c ,求解与其对应的next数组为多少 1.1 前置知识-最长公共前后缀LCP 1.1.1 前缀与后缀 前缀的概念:前缀是 不包含最后一个字符 的所有 以第一个字符开头 的任意子串 后缀的概念:后缀是 不包含第一个字符 的所有 以最后一个字符结尾 的任意子串 例

    2024年02月07日
    浏览(71)
  • 关于区块链的一点经济学思考

    区块链是区块链,加密资产是加密资产,尽管二者之间的关系紧密,区块链和加密资产却不能混为一谈。区块链并不是什么新技术,如果从创新的角度来看,顶多算是一种组合创新。但是,很少有一种技术像区块链这样,让很多人趋之若鹜,不论是技术人员还是普通大众,不

    2023年04月08日
    浏览(78)
  • freeRTOS中使用看门狗的一点思考

    关于看门狗想必各位嵌入式软件开发的朋友应该都不会陌生的。在嵌入式软件开发中,看门狗常被用于监测cpu的程序是否正常在运行,如果cpu程序运行异常会由看门狗在达到设定的阈值时触发复位,从而让整个cpu复位重新开始运行。 看门狗的本质是一个计数器,一开始的时候

    2024年02月03日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包