严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
严格相等运算符将告诉您两个对象类型是否相等。然而,是否有一种方法来判断两个对象是否相等,就像Java中的哈希码值一样?
堆栈溢出问题JavaScript中有hashCode函数吗?类似于这个问题,但需要一个更学术的答案。上面的场景说明了为什么有必要有一个,我想知道是否有等效的解决方案。
当前回答
如果两个对象的所有属性都具有相同的值,并且所有嵌套对象和数组都递归地具有相同的值,那么将它们视为相等是很有用的。我也认为以下两个对象是相等的:
var a = {p1: 1};
var b = {p1: 1, p2: undefined};
类似地,数组可以有“缺失”元素和未定义的元素。我也会同样对待它们:
var c = [1, 2];
var d = [1, 2, undefined];
函数:实现等式定义的函数:
function isEqual(a, b) {
if (a === b) {
return true;
}
if (generalType(a) != generalType(b)) {
return false;
}
if (a == b) {
return true;
}
if (typeof a != 'object') {
return false;
}
// null != {}
if (a instanceof Object != b instanceof Object) {
return false;
}
if (a instanceof Date || b instanceof Date) {
if (a instanceof Date != b instanceof Date ||
a.getTime() != b.getTime()) {
return false;
}
}
var allKeys = [].concat(keys(a), keys(b));
uniqueArray(allKeys);
for (var i = 0; i < allKeys.length; i++) {
var prop = allKeys[i];
if (!isEqual(a[prop], b[prop])) {
return false;
}
}
return true;
}
源代码(包括辅助函数,generalType和uniqueArray): 这里是单元测试和测试运行器。
其他回答
你可以使用_。isEqual(obj1, obj2)来自underscore.js库。
这里有一个例子:
var stooge = {name: 'moe', luckyNumbers: [13, 27, 34]};
var clone = {name: 'moe', luckyNumbers: [13, 27, 34]};
stooge == clone;
=> false
_.isEqual(stooge, clone);
=> true
在这里查看官方文档:http://underscorejs.org/#isEqual
如果使用JSON库,可以将每个对象编码为JSON,然后比较结果字符串是否相等。
var obj1={test:"value"};
var obj2={test:"value2"};
alert(JSON.encode(obj1)===JSON.encode(obj2));
注意:虽然这个答案在很多情况下都有效,但由于各种原因,一些人在评论中指出了它的问题。在几乎所有情况下,您都希望找到更健壮的解决方案。
假设对象中属性的顺序没有改变。
JSON.stringify()适用于深度和非深度这两种类型的对象,不太确定性能方面:
Var object1 = { 关键:“价值” }; Var object2 = { 关键:“价值” }; Var object3 = { 键:“无值” }; console.log('object1和object2相等:',JSON.stringify(object1) === JSON.stringify(object2)); console.log('object2和object3相等:',JSON.stringify(object2) === JSON.stringify(object3));
这是一个通用的相等检查函数,它接收数组元素作为输入,并将它们相互比较。适用于所有类型的元素。
const isEqual = function(inputs = []) {
// Checks an element if js object.
const isObject = function(data) {
return Object.prototype.toString.call(data) === '[object Object]';
};
// Sorts given object by its keys.
const sortObjectByKey = function(obj) {
const self = this;
if (!obj) return {};
return Object.keys(obj).sort().reduce((initialVal, item) => {
initialVal[item] = !Array.isArray(obj[item]) &&
typeof obj[item] === 'object'
? self.objectByKey(obj[item])
: obj[item];
return initialVal;
}, {});
};
// Checks equality of all elements in the input against each other. Returns true | false
return (
inputs
.map(
input =>
typeof input == 'undefined'
? ''
: isObject(input)
? JSON.stringify(sortObjectByKey(input))
: JSON.stringify(input)
)
.reduce(
(prevValue, input) =>
prevValue === '' || prevValue === input ? input : false,
''
) !== false
);
};
// Tests (Made with Jest test framework.)
test('String equality check', () => {
expect(isEqual(['murat'])).toEqual(true);
expect(isEqual(['murat', 'john', 'doe'])).toEqual(false);
expect(isEqual(['murat', 'murat', 'murat'])).toEqual(true);
});
test('Float equality check', () => {
expect(isEqual([7.89, 3.45])).toEqual(false);
expect(isEqual([7, 7.50])).toEqual(false);
expect(isEqual([7.50, 7.50])).toEqual(true);
expect(isEqual([7, 7])).toEqual(true);
expect(isEqual([0.34, 0.33])).toEqual(false);
expect(isEqual([0.33, 0.33])).toEqual(true);
});
test('Array equality check', () => {
expect(isEqual([[1, 2, 3], [1, 2, 3]])).toEqual(true);
expect(isEqual([[1, 3], [1, 2, 3]])).toEqual(false);
expect(isEqual([['murat', 18], ['murat', 18]])).toEqual(true);
});
test('Object equality check', () => {
let obj1 = {
name: 'murat',
age: 18
};
let obj2 = {
name: 'murat',
age: 18
};
let obj3 = {
age: 18,
name: 'murat'
};
let obj4 = {
name: 'murat',
age: 18,
occupation: 'nothing'
};
expect(isEqual([obj1, obj2])).toEqual(true);
expect(isEqual([obj1, obj2, obj3])).toEqual(true);
expect(isEqual([obj1, obj2, obj3, obj4])).toEqual(false);
});
test('Weird equality checks', () => {
expect(isEqual(['', {}])).toEqual(false);
expect(isEqual([0, '0'])).toEqual(false);
});
这里还有一个要点
我写这个方法只是为了确保数组和对象都能被清晰地比较。
这应该也能做到!:)
public class Objects {
/**
* Checks whether a value is of type Object
* @param value the value
*/
public static isObject = (value: any): boolean => {
return value === Object(value) && Object.prototype.toString.call(value) !== '[object Array]'
}
/**
* Checks whether a value is of type Array
* @param value the value
*/
public static isArray = (value: any): boolean => {
return Object.prototype.toString.call(value) === '[object Array]' && !Objects.isObject(value)
}
/**
* Check whether two values are equal
*/
public static isEqual = (objectA: any, objectB: any) => {
// Objects
if (Objects.isObject(objectA) && !Objects.isObject(objectB)) {
return false
}
else if (!Objects.isObject(objectA) && Objects.isObject(objectB)) {
return false
}
// Arrays
else if (Objects.isArray(objectA) && !Objects.isArray(objectB)) {
return false
}
else if (!Objects.isArray(objectA) && Objects.isArray(objectB)) {
return false
}
// Primitives
else if (!Objects.isArray(objectA) && !Objects.isObject(objectA)) {
return objectA === objectB
}
// Object or array
else {
const compareObject = (objectA: any, objectB: any): boolean => {
if (Object.keys(objectA).length !== Object.keys(objectB).length) return false
for (const propertyName of Object.keys(objectA)) {
const valueA = objectA[propertyName]
const valueB = objectB[propertyName]
if (!Objects.isEqual(valueA, valueB)) {
return false
}
}
return true
}
const compareArray = (arrayA: any[], arrayB: any[]): boolean => {
if (arrayA.length !== arrayB.length) return false
for (const index in arrayA) {
const valueA = arrayA[index]
const valueB = arrayB[index]
if (!Objects.isEqual(valueA, valueB)) {
return false
}
}
return true
}
if (Objects.isObject(objectA)) {
return compareObject(objectA, objectB)
} else {
return compareArray(objectA, objectB)
}
}
}
}