Сравнение типов, значений и объектов в 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", вы можете фактически сохранить это в строке вручную.

Другие вопросы по тегам