记录--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 ...
随机推荐
- Oracle如何限制非法调用包中过程
原文:http://www.oracle.com/technetwork/issue-archive/2015/15-jan/o15plsql-2398996.html 假如我有一个包P_A,其中封装 ...
- 突破Windows的极限
偶然碰到这类技术博客,甚感欣慰,但奈何技术水平达不到,很多都难以理解,故记录在此,用作日后学习. 国内有类似的中文翻译,比如:突破Windows极限:物理内存 但是外文链接已经失效,看不到原汁原味的英 ...
- win32 - EnumDisplayDevices和EnumDisplayMonitors的使用
EnumDisplayDevices枚举适配器 EnumDisplayMonitors枚举监视器 #pragma comment(lib, "dxva2.lib") #includ ...
- MySQL重新设置auto_increment值
需求描述 通常,我们都会在数据库表中设置一个自增字段作为主键,该字段的值会随着添加新记录而自增. 同时也必须注意,这个自增字段的值只会一直增加,即使把记录删除了,该自增字段的值也不会变小. 因此,就会 ...
- JavaScript的引入并执行-包含动态引入与静态引入
JavaScript的引入并执行-包含动态引入与静态引入 JavaScript引入方式 html文件需要引入JavaScript代码,才能在页面里使用JavaScript代码. 静态引入 行内式 直接 ...
- Mysql 插入timestamp没有使用默认值问题
在一次升级过程中,发现Mysql插入数据报了个错 Column 'create_time' cannot be null. 但是看了下这个字段虽然是非null,但是是有默认值的 `create_tim ...
- Qt开发技术:QtCharts(一)QtCharts基本介绍以及图表框架详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- linux下安装nginx(yum源安装)
备份yum源 cd /etc/yum.repos.d mkdir repo_bak mv *.repo repo_bak/ 下载阿里云repo文件 wget -O /etc/yum.repos.d/C ...
- 文心一言 VS 讯飞星火 VS chatgpt (203)-- 算法导论15.3 2题
二.对一个16个元素的数组,画出2.3.1节中MERGE-SORT过程运行的递归调用树.解释备忘技术为什么对MERGE-SORT这种分治算法无效.需要写代码的时候,请用go语言. 文心一言,代码不完整 ...
- 【Azure Developer】Python 读取 json文件及过滤出需要的结果
问题描述 首先,有名为 campsites.json 的JSON数据文件,数据格式为 { "type": "FeatureCollection", " ...
