Сравнение типов, значений и объектов в JavaScript (не дубликат)
Изменить: это не повторяющийся вопрос. Моя функция отличается и не использует методы прямого сравнения объектов.
Я работаю над книгой Eloquent Javascript, и в четвертой главе последнему упражнению потребовалась функция deepEqual, которая принимает два аргумента и сравнивает их.
- Если аргументы имеют разные типы, он должен вернуть false.
- Если аргументы имеют один и тот же тип и одно и то же значение, в противном случае он должен вернуть true, вернуть false.
- Если оба аргумента являются объектами, их свойства и значения должны сравниваться. Вызов функции должен возвращать true, если оба объекта имеют одинаковые свойства и значение в одном и том же порядке. Например, если у нас есть следующие объекты:
object1 = {a: 1, b: 2}, object2 = {a: 1, b: 2}, object3 = {a: 2, b: 1}
сравнение object1 и object2 должно возвращать true, но сравнение object1 и object3 должно возвращать false. - Наконец, если объекты имеют вложенные объекты в качестве параметров, рекурсивный вызов deepEqual для сравнения вложенных объектов.
Итак, вот мое решение. Это довольно запутанно с заявлениями if/else, простите это.
function deepEqual(obj1, obj2){
var checkForSameTypes = (typeof obj1 === typeof obj2);
if(checkForSameTypes === true){
//same type but not objects
if(typeof obj1 !== "object" && typeof obj2 !== "object") {
if(obj1 == obj2){
return true;
}else{
return false;
}
// same type and objects
}else if(typeof obj1 === "object" && typeof obj2 === "object"){
//loop first object and compare properties with 2nd object
for(var prop in obj1){
if(obj2.hasOwnProperty(prop)) {
//if 2nd object has property "prop" compare
if(typeof obj1[prop] === "object" && typeof obj2[prop] === "object"){
//recursive call
deepEqual(obj1[prop], obj2[prop]);
}else if(obj1[prop] === obj2[prop]) {
//loop goes on to the next property
continue;
}else if(obj1[prop] !== obj2[prop]){
return false;
}
//it doesn't have property "prop" so return false
} else {
return false;
}
}
//finishes loop and all properties are the same
return true;
}
// they are not the same types so return false
} else {
return false;
}
}
ПРОБЛЕМА
Функция работает нормально, за исключением случаев, когда аргумент является объектом с вложенными объектами. Возьмите эти объекты например
var type = {go: {inside: "yes"}, come: 2}
var see = {go: {inside: "no"}, come: 2}
var fine = {when: 3, go: 4};`
Когда я сравниваю type
а также see
с призывом к deepEqual(type,see);
, это возвращает true
что неверно, поскольку значение свойства вложенного объекта go
это отличается.
Я просмотрел весь код на бумаге, построчно и не знаю, что мне делать, или если рекурсивный вызов не работает для правильного сравнения свойств, или у меня просто еще нет знаний.
Кто-нибудь может предложить решение? или и если возможно лучший способ или процесс мышления, чтобы решить это дело?
Примечание. Код сравнивает только свойства и значения объекта. Не нужно сравнивать конструкторы или прототипы.
1 ответ
Существует много методов глубокого сравнения объектов, но, вероятно, самый надежный и самый простой... Использование JSON.stringify(obj)
на каждый объект для сравнения, который превращает их в строки, а затем сравнивает строки.
var a = {go: {inside: "yes"}, come: 2, flag: true}
var b = {go: {inside: "yes"}, come: 2, flag: true}
var c = {go: {inside: "yes"}, come: 1}
var d = {go: {inside: "yes"}, come: 2, flag: "true"}
function deepEqual(obj1, obj2){
// Convert both objects to strings and compare them:
console.log(JSON.stringify(obj1) === JSON.stringify(obj2));
}
deepEqual(a,b); // true
deepEqual(b,c); // false
deepEqual(a,d); // false
Теперь имейте в виду, что JSON.stringify()
удаляет свойства, по умолчанию сохраняющие функции из соображений безопасности, но используя необязательный аргумент "replacer", вы можете фактически сохранить это в строке вручную.