惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Help Net Security
云风的 BLOG
云风的 BLOG
Apple Machine Learning Research
Apple Machine Learning Research
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
D
Docker
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
博客园 - Franky
B
Blog RSS Feed
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
量子位
V
Visual Studio Blog
Y
Y Combinator Blog
小众软件
小众软件
N
Netflix TechBlog - Medium
博客园 - 三生石上(FineUI控件)
Microsoft Security Blog
Microsoft Security Blog
雷峰网
雷峰网

开飞机的老张

AGENTS.md Openspec 使用心得 从树莓派内网穿透到 Cloudflare Pages Openclaw和博客 郊眠寺 采石 译:我为什么使用Map(和WeakMap)处理DOM节点 介绍JavaScript中Symbol 原生JavaScript获取URL参数 字符串首字母大写 用forEach()遍历对象 JavaScript禁用按钮 JavaScript的FormData JavaScript的Blob 用FileReader读取本地文件 JavaScript的Thenable JavaScript中Promise的reject JavaScript的立即调用函数表达式(IIFE) JavaScript的Promise链 用interact.js实现拖拽、缩放、吸附 使用bluebird操作Promise JavaScript创建Promise JavaScript中Promise的catch函数
JavaScript比较数组
kaifeiji.cc · 2023-02-28 · via 开飞机的老张

原文:Compare Arrays in JavaScript

JavaScript比较两个数组的一些技巧。

JavaScript中的数组本质是对象,因此用===比较,只有在数组是相同引用时才会返回true

1
2
3
4
5
const a = [1, 2, 3];
const b = [1, 2, 3];

a === a;
a === b;

如何判断两个数组相等?相等是个棘手的问题:JavaScript标准定义了4种不同的方法,用于检查两个值是否“相等”,但都没有考虑到深入对象内部的相等。

在某些场景下,你需要尽可能精确的定义“相等”。在软件工程中,提出正确的问题往往能够得到明显的答案。

基于这些原则,本文提供了3种数组相等的定义,以及如何判断相等。

相同长度、每个值相等

比较ab的一种方式,是检查a的每个值是否严格等于b的对应值。当数组元素都是原始类型而非对象时很容易实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [1, 2, 3];

function arrayEquals(a, b) {
return Array.isArray(a) &&
Array.isArray(b) &&
a.length === b.length &&
a.every((val, index) => val === b[index]);
}

arrayEquals(a, b);
arrayEquals(a, c);

POJO的深度相等

上文的arrayEquals()函数对原始类型值运行正常,但想要比较对象数组就麻烦了。

1
2
3
4
5
const a = [{ answer: 42 }, { powerLevel: 9001 }];
const b = [{ answer: 42 }, { powerLevel: 9001 }];


arrayEquals(a, b);

考虑到对象数组的比较,一种简单的方式是用JSON.stringify()

1
2
3
4
5
6
const a = [{ answer: 42 }, { powerLevel: 9001 }];
const b = [{ answer: 42 }, { powerLevel: 9001 }];
const c = [{ answer: 42 }, { password: 'taco' }];

JSON.stringify(a) === JSON.stringify(b);
JSON.stringify(a) === JSON.stringify(c);

这种方式很方便,它需要很少的代码而且不会引用到外部库。但是比较JSON.stringify()的输出,根据使用的不同,边界情况下可能会发生意外。由于undefined不是有效的JSON值,以下数组具有相同的JSON.stringify()输出,因为JSON.stringify()undefined转换为null

1
2
const a = [undefined];
const b = [null];

使用lodash的isEqual()

除了nullundefined的问题,比较JSON.stringify()的输出也没有考虑对象类型。一个对象,带有一个返回42toJSON()函数,它的JSON.stringify()输出和数值42完全相同。

1
2
3
4
5
const a = [{ toJSON: () => 42 }];
const b = [42];

JSON.stringify(a);
JSON.stringify(b);

相似的,自定义对象和POJO的JSON.stringify()也是相同的:

1
2
3
4
5
6
7
8
9
10
class MyClass {
constructor(obj) {
Object.assign(this, obj);
}
}

const a = [new MyClass({ answer: 42 })];
const b = [{ answer: 42 }];

JSON.stringify(a) === JSON.stringify(b);

JSON.stringify()不同,lodash的isEqual()函数考虑了以上所有情况。

1
2
3
4
5
6
7
8
9
10
11
12
const _ = require('lodash');

class MyClass {
constructor(obj) {
Object.assign(this, obj);
}
}

const a = [new MyClass({ answer: 42 })];
const b = [{ answer: 42 }];

_.isEqual(a, b);

如果你需要比较类的对象或者其他花里胡哨的东西,lodash的isEqual()函数是正确的方式。JSON.stringify()对POJO而言是可用的,但是一定要考虑到undefinednull,而且只对可信的数据使用——toJSON()可能造成安全漏洞。