百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

为什么Array.every() 对于空数组总是返回 true?

toyiye 2024-08-19 22:30 3 浏览 0 评论

今天我们从源头探寻一下 Array.prototype.every 这个方法,便于正确理解这个知识点。

疑问点(懵逼的地方)

这个执行结果,看着有些和我们预想的结果不一样,期待的是false,所以疑问就产生了。

开始分析

MDN 这样描述:

every() 方法测试一个数组内的所有元素是否都能通过指定函数的测试。它返回一个布尔值。

const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
// Expected output: true

看了 MDN 的描述后,你是不是依然懵逼中; 其实它的描述不是那么准确,哈哈

我们来看看 ecma262 标准是怎么解释的:

23.1.3.6 Array.prototype.every ( callbackfn [ , thisArg ] )

callbackfn should be a function that accepts three arguments and returns a value that is coercible to a Boolean value. every calls callbackfn once for each element present in the array, in ascending order, until it finds one where callbackfn returns false. If such an element is found, every immediately returns false. Otherwise, every returns true. callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.

If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackfn. If it is not provided, undefined is used instead.

callbackfn is called with three arguments: the value of the element, the index of the element, and the object being traversed.

every does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.

The range of elements processed by every is set before the first call to callbackfn. Elements which are appended to the array after the call to every begins will not be visited by callbackfn. If existing elements of the array are changed, their value as passed to callbackfn will be the value at the time every visits them; elements that are deleted after the call to every begins and before being visited are not visited. every acts like the "for all" quantifier in mathematics. In particular, for an empty array, it returns true.

This method performs the following steps when called:

  1. Let O be ? ToObject(this value).
  2. Let len be ? LengthOfArrayLike(O).
  3. If IsCallable(callbackfn) is false, throw a TypeError exception.
  4. Let k be 0.
  5. Repeat, while k < len, a. Let Pk be ! ToString((k)). b. Let kPresent be ? HasProperty(O, Pk). c. If kPresent is true, then i. Let kValue be ? Get(O, Pk). ii. Let testResult be ToBoolean(? Call(callbackfn, thisArg, ? kValue, (k), O ?)). iii. If testResult is false, return false. d. Set k to k + 1.
  6. Return true.

翻译一下,大概意思是:

callbackfn 应该是一个接受三个参数并返回一个可转换为布尔值的函数。every 会对数组中的每个元素(按升序)调用 callbackfn,直到找到一个使 callbackfn 返回 false 的元素。如果找到了这样的元素,every 会立即返回 false。否则,every 返回 truecallbackfn 只对数组中实际存在的元素调用,不会对缺失的元素调用。

如果提供了 thisArg 参数,它将作为每次调用 callbackfn 时的 this 值。如果未提供,则使用 undefined

调用 callbackfn 时会传递三个参数:元素的值、元素的索引和被遍历的对象。

every 方法不会直接修改调用它的对象,但对象可能会被调用 callbackfn 时的操作修改。

every 方法在第一次调用 callbackfn 之前就已经确定了处理的元素范围。追加到数组中的元素在 every 开始调用后不会被 callbackfn 访问。如果数组中的现有元素在 every 开始调用后被更改,则传递给 callbackfn 的值将是 every 访问它们时的值;在调用 every 之后但在访问之前被删除的元素不会被访问。every 类似于数学中的“全称量化”运算符。特别是对于一个空数组,它返回 true

相信当你看到这里时,已经解答了你心中的疑惑了吧。这就是规范里的官方解释!

什么,你说你还是懵逼的,觉得这不够直观,好的,明白 ,安排(我们直接上代码,给你最直观的感受,这总行了吧!)

我们现在就把 every 方法在调用时执行的步骤(就是上面没有翻译的那6点),用 JS 来模拟写出来(便于我们直接理解学习),因为在 V8 里的 every方法的源码是用 c++ 实现的。话不多说,开搞:

Array.prototype.myEvery = function(callbackfn, thisArg) {
    // 1. 将 this 值转换为对象。
    if (this == null) {
        throw new TypeError('Array.prototype.myEvery called on null or undefined');
    }
    const O = Object(this);

    // 2. 获取数组的长度。
    const len = O.length >>> 0;

    // 3. 如果 callbackfn 不是函数,则抛出 TypeError 异常。
    if (typeof callbackfn !== 'function') {
        throw new TypeError(callbackfn + ' is not a function');
    }

    // 4. 初始化索引 k 为 0。
    let k = 0;

    // 5. 当 k 小于 len 时,重复以下步骤:
    while (k < len) {
        // a. 将 k 转换为字符串 Pk。
        const Pk = k.toString();

        // b. 检查 O 是否具有属性 Pk。
        const kPresent = Pk in O;

        // c. 如果属性存在:
        if (kPresent) {
            // i. 获取属性值 kValue。
            const kValue = O[Pk];

            // ii. 使用 callbackfn 调用该值,并将结果转换为布尔值。
            const testResult = Boolean(callbackfn.call(thisArg, kValue, k, O));

            // iii. 如果结果为 false,立即返回 false。
            if (!testResult) {
                return false;
            }
        }
        // d. 增加 k。
        k++;
    }

    // 6. 如果所有元素都满足条件,返回 true。
    return true;
};

// 测试示例

const data1 = [1, 2, 3, 4].myEvery(num => num > 0); // 应该返回 true
const data2 = [1, 2, 3, -1].myEvery(num => num > 0); // 应该返回 false
const data3 = [].myEvery(num => num > 0); // 应该返回 true

console.log(data1); // true
console.log(data2); // false
console.log(data3); // true

这下够直观了吧。在上面 的代码里可以看见:当数组的长度为 0 时,就不会循环执行第 5 点,直接返回 true 了

最后

有什么观点或者疑问,欢迎在评论区留言,我们一起交流学习 !

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码