记录--JavaScript 令人惊讶的一点:对于空数组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的更多相关文章
- 空数组判断false、true的情况
- JavaScript中判断变量类型最简洁的实现方法以及自动类型转换(#################################)
这篇文章主要介绍了JavaScript中判断整字类型最简洁的实现方法,本文给出多个判断整数的方法,最后总结出一个最短.最简洁的实现方法,需要的朋友可以参考下 我们知道JavaScript提供了type ...
- js 判断是否为空对象、空数组
当需要判断参数是否为空时,总希望 js 能够提供原生的判断方法,可惜并没有,只能自己封装了. function isEmpty(obj) { // 检验 undefined 和 null if(!ob ...
- node.js 开发桌面程序, 10个令人惊讶的NodeJS开源项目
用 node-webkit 开源框架. 做企业站,杠杠地 包括电子书和支付宝系统都是node开发的,. 接收传感器发送的数据再运算...对水泵.风机.空调这些硬件进行远程控制. 细数10个令人惊讶的N ...
- javascript中怎么判断对象{}为空
有时候通过AJAX方法调用返回的是一个JSON对象,而这个对象可能在开发过程中会没有数据是一个空{}. JavaScript判断object/json 是否为空,可以使用jQuery的isEmptyO ...
- 【06】Firebug记录Javascript日志
Firebug记录Javascript日志 你可以使用Firebug来生成日志. 这有助于我们调试web页面并发现页面的错误. 在Firefox浏览器中执行以下代码: <!DOCTYPE HTM ...
- JavaScript的json和Array及Array数组的使用方法
1.关于json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集.也可以称为数据集和数组类似,能够存数据! //Ar ...
- javascript中数组的方法你真的都了解吗?
本篇文章主要讲述ES5中的数组,包括数组两种创建方式,属性,以及 9 大类 ,总共23个操作方法,非常全面,看完之后ES5数组这一部分基本都了解了,下一篇文章,我会讲述ES6中对数组的加成,新增了哪些 ...
- JavaScript进阶 - 第3章 一起组团(数组)
第3章 一起组团(数组) 3-1 一起组团(什么是数组) 我们知道变量用来存储数据,一个变量只能存储一个内容.假设你想存储10个人的姓名或者存储20个人的数学成绩,就需要10个或20个变量来存储,如果 ...
- JavaScript中操作数组的方法
JavaScript Array 对象 对数组操作的方法分为两种 一种是会改变原始数组的变异方法,还有一种是不会改变原始数组的非变异方法. 总结 巧记 Push() 尾部添加 pop() 尾部删除 U ...
随机推荐
- [Spring6.0源码解析]简述@Configuration注解
@Configuration 标注在类上,启动 Spring 会自动扫描@Configuration注解的类,将其注册到IOC容器并实例化bean对象.如果在@Configuration注解的类中使用 ...
- BeginCTF 2024(自由赛道)MISC
real check in 题目: 从catf1y的笔记本中发现了这个神秘的代码 MJSWO2LOPNLUKTCDJ5GWKX3UN5PUEM2HNFXEGVCGL4ZDAMRUL5EDAUDFL5M ...
- P1405 苦恼的小明 题解
题目传送门 前置知识 扩展欧拉定理 解法 本题幂塔是有限层的,这里与 luogu P4139 上帝与集合的正确用法 中的无限层幂塔不同,故需要在到达递归边界 \(n+1\) 时进行特殊处理,对于处理 ...
- NC14419 线路规划
题目链接 题目 题目描述 Q国的监察院是一个神秘的组织. 这个组织掌握了整个帝国的地下力量,监察着Q国的每一个人. 监察院一共有N个成员,每一个成员都有且仅有1个直接上司,而他只听从其上直接司的命令. ...
- 【Unity3D】人物跟随鼠标位置
1 游戏对象 2D动画和人体模型及动画中介绍了 Aniamtion.Animator.人体模型.人体骨骼.人体动画等基础知识,本文将通过 "人物跟随鼠标位置" 案例加强对 Un ...
- Oracle设置和删除不可用列
Oracle设置和删除不可用列 1.不可用列是什么? 就是表中的1个或多个列被ALTER TABLE-SET UNUSED 语句设置为无法再被程序利用的列. 2.使用场景? If you are co ...
- 《系列二》-- 5、单例bean缓存的获取
目录 1 判断bean是否完成整个加载流程 2 判断当前bean是否被加载过,是否已作为提前暴露的bean 关于循环依赖 阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内 ...
- 在SpringBoot中实践AOP编程
具体实践 Spring AOP是Spring框架中一个支持实现面向切面编程的模块,由于Spring Boot已经把Spring框架组合得非常好用,所以在基于Spring Boot框架的项目中实现AOP ...
- Redis居然还有比RDB和AOF更强大的持久化方式?
https://cloud.tencent.com/developer/article/1786055
- go值接收者和指针接收者的区别
方法的接收者 package main import ( "fmt" ) type Person struct { Name string Age int } func (p Pe ...
