JavaScript 中很多情况下你需要判断在数组中是否存在某对象元素,然而与在 JavaScript 判断数组中是否包含某个数字或字符串元素不同,最好不要使用 Array.includes() 和 Array.indexOf() 方法。如果要在 JS 中判断数组是否包含数字或字符串元素,请查看:JS : JavaScript 判断数组中是否包含某个元素(数字、字符串,含最简方法)

本文将介绍在 Javascript 中判断数组中是否存在某个对象(Object)元素的多个方法:

  • 推荐:js 使用 Array.some(callbackFn) 方法判断数组包含对象元素
  • js 使用 Array.find(callbackFn) 方法判断数组包含对象元素

不使用 Array.includes() 和 Array.indexOf() 方法的原因

为什么不能使用 Array.includes() 或 Array.indexOf() 方法判断数组是否包含某个对象元素,请看如下的示例:

const wang = {
    'name': 'Wang',
    'email': 'wang@51shizhi.com'
};
const li = {
    'name': 'Li',
    'email': 'li@51shizhi.com'
};

const persons = [wang, li];
let result = persons.includes(wang);

console.log(result);

在如上示例中,persons 数组包含了 wang 对象的引用,因此使用 persons.includes(wang) 判断会返回 true

在实际应用中,你所查询的不是对象的引用相同,而是对象包含相同的属性和值,如下示例则不能得出正确的结果:

const wang = {
    'name': 'Wang',
    'email': 'wang@51shizhi.com'
};
const li = {
    'name': 'Li',
    'email': 'li@51shizhi.com'
};

const persons = [wang, li];
let result = persons.includes({
    'name': 'Wang',
    'email': 'wang@51shizhi.com'
});

console.log(result);
// 输出为: false

然而,如上示例,使用 persons.includes() 判断会返回 false,因为 persons 数组没有包含了搜索对象的引用。

因此,在 js 中不能使用 Array.includes() 和 Array.indexOf() 方法判断数组是否包含对象元素。

推荐:js 使用 Array.some() 方法判断数组包含对象元素

Array.some() 方法可以用来判断在 JS 数组中是否存在某个数字或字符串元素,但是需要传入一个回调函数,该方法会对数组中的每个元素调用回调函数,如果存在元素使回调函数返回 true,则该函数返回 true,否则返回 false

在 JS 使用 Array.some() 方法判断数组是否包含对象元素,需要如下两个步骤:

  • 定义一个函数用于判断:两个对象的属性和值相同
  • 使用 Array.some() 方法传入判断对象属性值相同的函数

1、基于 Object.keys() 自定义判断两个对象的属性和值相同的函数:

function isEqual(obj, other) {
    let obj_keys = Object.keys(obj);
    let other_keys = Object.keys(other);
    if (obj_keys.length != other_keys.length) {
        return false;
    }
    // 排序 keys,因为需要比较 key 是否相等
    obj_keys.sort();
    other_keys.sort();
    // 使用 obj_keys.length 或 other_keys.length 都可以,因为值相同
    for (let i=0; i<obj_keys.length; i++) {
        if (obj_keys[i] != other_keys[i] || obj[obj_keys[i]] != other[other_keys[i]]) {
            return false;
        }
    }
    return true;
}

解释说明

当两个对象的属性和值相同时返回 true,否则返回 false

注:也可以使用 Lodash 提供的 isEqual() 函数,它更好用,只是需要导入 Lodash 库,本文提供自己打包的 Lodash isEqual() 函数的单函数文件,供你使用;同时不推荐使用 JSON.stringify() 自定义函数,具体查看:JS : Javascript 如何判断对象是否相等

2、使用 Array.some() 方法传入函数判断两个对象是否相同:

function isEqual(obj, other) {
    let obj_keys = Object.keys(obj);
    let other_keys = Object.keys(other);
    if (obj_keys.length != other_keys.length) {
        return false;
    }
    // 排序 keys,因为需要比较 key 是否相等
    obj_keys.sort();
    other_keys.sort();
    // 使用 obj_keys.length 或 other_keys.length 都可以,因为值相同
    for (let i=0; i<obj_keys.length; i++) {
        if (obj_keys[i] != other_keys[i] || obj[obj_keys[i]] != other[other_keys[i]]) {
            return false;
        }
    }
    return true;
}

const wang = {
    'name': 'Wang',
    'email': 'wang@51shizhi.com'
};
const li = {
    'name': 'Li',
    'email': 'li@51shizhi.com'
};

const persons = [wang, li];
const result = persons.some(element => isEqual(element, {
    'name': 'Wang',
    'email': 'wang@51shizhi.com'
})); 

console.log(result);
// 输出为: true

解释说明:

  • 定义一个函数 isEqual 用于判断元素是否相等,相等返回 true,不相等返回 false

js 使用 Array.find() 方法判断数组包含对象元素

Array.find() 方法可以用来判断在 JS 数组中是否存在某个数字或字符串元素,但是需要传入一个回调函数,该方法会对数组中的每个元素调用回调函数,如果存在元素使回调函数返回 true,则该函数返回匹配到的元素,否则返回 undefined

与使用 Array.some() 方法相似,在 JS 中使用 Array.find() 方法判断数组是否包含对象元素,需要如下两个步骤:

  • 定义一个函数用于判断:两个对象的属性和值相同
  • 使用 Array.find() 方法传入判断对象属性值相同的函数

1、基于 Object.keys() 自定义判断两个对象的属性和值相同的函数:

function isEqual(obj, other) {
    let obj_keys = Object.keys(obj);
    let other_keys = Object.keys(other);
    if (obj_keys.length != other_keys.length) {
        return false;
    }
    // 排序 keys,因为需要比较 key 是否相等
    obj_keys.sort();
    other_keys.sort();
    // 使用 obj_keys.length 或 other_keys.length 都可以,因为值相同
    for (let i=0; i<obj_keys.length; i++) {
        if (obj_keys[i] != other_keys[i] || obj[obj_keys[i]] != other[other_keys[i]]) {
            return false;
        }
    }
    return true;
}

解释说明

当两个对象的属性和值相同时返回 true,否则返回 false

注:也可以使用 Lodash 提供的 isEqual() 函数,它更好用,只是需要导入 Lodash 库,本文提供自己打包的 Lodash isEqual() 函数的单函数文件,供你使用;同时不推荐使用 JSON.stringify() 自定义函数,具体查看:JS : Javascript 如何判断对象是否相等

2、使用 Array.find() 方法传入函数判断两个对象是否相同:

const wang = {
    'name': 'Wang',
    'email': 'wang@51shizhi.com'
};
const li = {
    'name': 'Li',
    'email': 'li@51shizhi.com'
};

const persons = [wang, li];

function isEqual(obj, other) {
    let obj_keys = Object.keys(obj);
    let other_keys = Object.keys(other);
    if (obj_keys.length != other_keys.length) {
        return false;
    }
    // 排序 keys,因为需要比较 key 是否相等
    obj_keys.sort();
    other_keys.sort();
    // 使用 obj_keys.length 或 other_keys.length 都可以,因为值相同
    for (let i=0; i<obj_keys.length; i++) {
        if (obj_keys[i] != other_keys[i] || obj[obj_keys[i]] != other[other_keys[i]]) {
            return false;
        }
    }
    return true;
}
/* 定义一个判断数组中是否包含某个元素的方法,
 * @param {Array} arr
 * @param {element} element
 */
function isExist(arr, obj) {
    let result = persons.find(element => isEqual(element, obj));
    if (result) {
        return true;
    }
    return false;
}

console.log(isExist(persons, wang));
// 输出为: true

console.log(isExist(persons, {
    'name': 'Zhang',
    'email': 'zhang@51shizhi.com'
}));
// 输出为: false

解释说明:

  • 定义一个函数 isExist 用于判断数组是否包含元素,第一个参数为数组,第二个参数为元素
  • 定义一个函数 isEqual 用于判断两个对象元素是否相等,相等返回 true,不相等返回 false
  • 执行 isExist 判断数组是否存在元素

结语

本文介绍了在 Javascript 中判断数组中是否存在某个对象(Object)元素的多个方法:js 使用 Array.some(callbackFn) 方法判断数组包含对象元素,js 使用 Array.find(callbackFn) 方法判断数组包含对象元素。