Как определить равенство для двух объектов JavaScript?

Ваш код работает нормально.

Используйте Notepad2 или Notepad ++ , если вы работаете в Windows. Встроенный блокнот не может справиться с окончанием строки в стиле Unix.

569
задан Community 23 May 2017 в 12:10
поделиться

21 ответ

короткий ответ

простой ответ: Нет, нет никакого универсального средства решить, что объект равен другому в смысле, который Вы имеете в виду. Исключение - при строгом размышлении об объекте, являющемся без типов.

длинный ответ

понятие является понятием, Равняется методу, который сравнивает два различных экземпляра объекта указать, равны ли они на уровне значения. Однако это до определенного типа, чтобы определить, как Equals метод должен быть реализован. Повторяющееся сравнение атрибутов, которые имеют примитивные значения, не может быть достаточно, могут быть атрибуты, которые нельзя считать частью объектного значения. Например,

 function MyClass(a, b)
 {
     var c;
     this.getCLazy = function() {
         if (c === undefined) c = a * b // imagine * is really expensive
         return c;
     }
  }

В этом выше случая, c не действительно важно, чтобы определить, равны ли какие-либо два экземпляра MyClass, [только 113] и b важны. В некоторых случаях c мог бы варьироваться между экземплярами и все же не быть значительным во время сравнения.

Примечание эта проблема применяется, когда участники могут самостоятельно также быть экземплярами типа, и они каждый был бы все обязан иметь средство определения равенства.

Дальнейшие усложняющие вещи состоят в том, что в JavaScript различие между данными и методом размывается.

объект может сослаться на метод, который нужно назвать как обработчик событий, и это, вероятно, не считали бы частью его 'состояния значения'. Принимая во внимание, что другому объекту можно присвоить функция, которая выполняет важное вычисление и таким образом делает этот экземпляр отличающимся от других просто, потому что это ссылается на различную функцию.

Что относительно объекта, который имеет один из его существующих методов прототипа, переопределенных другой функцией? Это можно было все еще считать равным другому экземпляру что это в других отношениях идентичный? На тот вопрос можно только ответить в каждом конкретном случае для каждого типа.

, Как указано ранее, исключением был бы объект строго без типов. В этом случае единственным разумным выбором является повторяющееся и рекурсивное сравнение каждого участника. Даже тогда нужно спросить, каково 'значение' функции?

162
ответ дан Peter Mortensen 23 May 2017 в 12:10
поделиться

Извлечение из моей личной библиотеки, которую я неоднократно использую для своей работы. Следующая функция является мягким рекурсивным глубоким равенством, которое не проверяет

  • Равенство классов
  • Унаследованные значения
  • Значения строгого равенства

Я в основном использую это, чтобы проверить, получаю ли я равные ответы на различные реализации API. Где может возникнуть разница в реализации (например, строка против числа) и дополнительные нулевые значения.

Его реализация довольно проста и коротка (если все комментарии удалены)

/** Recursively check if both objects are equal in value
***
*** This function is designed to use multiple methods from most probable 
*** (and in most cases) valid, to the more regid and complex method.
***
*** One of the main principles behind the various check is that while
*** some of the simpler checks such as == or JSON may cause false negatives,
*** they do not cause false positives. As such they can be safely run first.
***
*** # !Important Note:
*** as this function is designed for simplified deep equal checks it is not designed
*** for the following
***
*** - Class equality, (ClassA().a = 1) maybe valid to (ClassB().b = 1)
*** - Inherited values, this actually ignores them
*** - Values being strictly equal, "1" is equal to 1 (see the basic equality check on this)
*** - Performance across all cases. This is designed for high performance on the
***   most probable cases of == / JSON equality. Consider bench testing, if you have
***   more 'complex' requirments
***
*** @param  objA : First object to compare
*** @param  objB : 2nd object to compare
*** @param  .... : Any other objects to compare
***
*** @returns true if all equals, or false if invalid
***
*** @license Copyright by eugene@picoded.com, 2012.
***          Licensed under the MIT license: http://opensource.org/licenses/MIT
**/
function simpleRecusiveDeepEqual(objA, objB) {
	// Multiple comparision check
	//--------------------------------------------
	var args = Array.prototype.slice.call(arguments);
	if(args.length > 2) {
		for(var a=1; a<args.length; ++a) {
			if(!simpleRecusiveDeepEqual(args[a-1], args[a])) {
				return false;
			}
		}
		return true;
	} else if(args.length < 2) {
		throw "simpleRecusiveDeepEqual, requires atleast 2 arguments";
	}
	
	// basic equality check,
	//--------------------------------------------
	// if this succed the 2 basic values is equal,
	// such as numbers and string.
	//
	// or its actually the same object pointer. Bam
	//
	// Note that if string and number strictly equal is required
	// change the equality from ==, to ===
	//
	if(objA == objB) {
		return true;
	}
	
	// If a value is a bsic type, and failed above. This fails
	var basicTypes = ["boolean", "number", "string"];
	if( basicTypes.indexOf(typeof objA) >= 0 || basicTypes.indexOf(typeof objB) >= 0 ) {
		return false;
	}
	
	// JSON equality check,
	//--------------------------------------------
	// this can fail, if the JSON stringify the objects in the wrong order
	// for example the following may fail, due to different string order:
	//
	// JSON.stringify( {a:1, b:2} ) == JSON.stringify( {b:2, a:1} )
	//
	if(JSON.stringify(objA) == JSON.stringify(objB)) {
		return true;
	}
	
	// Array equality check
	//--------------------------------------------
	// This is performed prior to iteration check,
	// Without this check the following would have been considered valid
	//
	// simpleRecusiveDeepEqual( { 0:1963 }, [1963] );
	//
	// Note that u may remove this segment if this is what is intended
	//
	if( Array.isArray(objA) ) {
		//objA is array, objB is not an array
		if( !Array.isArray(objB) ) {
			return false;
		}
	} else if( Array.isArray(objB) ) {
		//objA is not array, objB is an array
		return false;
	}
	
	// Nested values iteration
	//--------------------------------------------
	// Scan and iterate all the nested values, and check for non equal values recusively
	//
	// Note that this does not check against null equality, remove the various "!= null"
	// if this is required
	
	var i; //reuse var to iterate
	
	// Check objA values against objB
	for (i in objA) {
		//Protect against inherited properties
		if(objA.hasOwnProperty(i)) {
			if(objB.hasOwnProperty(i)) {
				// Check if deep equal is valid
				if(!simpleRecusiveDeepEqual( objA[i], objB[i] )) {
					return false;
				}
			} else if(objA[i] != null) {
				//ignore null values in objA, that objB does not have
				//else fails
				return false;
			}
		}
	}
	
	// Check if objB has additional values, that objA do not, fail if so
	for (i in objB) {
		if(objB.hasOwnProperty(i)) {
			if(objB[i] != null && !objA.hasOwnProperty(i)) {
				//ignore null values in objB, that objA does not have
				//else fails
				return false;
			}
		}
	}
	
	// End of all checks
	//--------------------------------------------
	// By reaching here, all iteration scans have been done.
	// and should have returned false if it failed
	return true;
}

// Sanity checking of simpleRecusiveDeepEqual
(function() {
	if(
		// Basic checks
		!simpleRecusiveDeepEqual({}, {}) ||
		!simpleRecusiveDeepEqual([], []) ||
		!simpleRecusiveDeepEqual(['a'], ['a']) ||
		// Not strict checks
		!simpleRecusiveDeepEqual("1", 1) ||
		// Multiple objects check
		!simpleRecusiveDeepEqual( { a:[1,2] }, { a:[1,2] }, { a:[1,2] } ) ||
		// Ensure distinction between array and object (the following should fail)
		simpleRecusiveDeepEqual( [1963], { 0:1963 } ) ||
		// Null strict checks
		simpleRecusiveDeepEqual( 0, null ) ||
		simpleRecusiveDeepEqual( "", null ) ||
		// Last "false" exists to make the various check above easy to comment in/out
		false
	) {
		alert("FATAL ERROR: simpleRecusiveDeepEqual failed basic checks");
	} else { 
		//added this last line, for SO snippet alert on success
		alert("simpleRecusiveDeepEqual: Passed all checks, Yays!");
	}
})();
2
ответ дан PicoCreator 23 May 2017 в 12:10
поделиться

Если Вы пользуетесь библиотекой JSON, можно закодировать каждый объект JSON, то сравнить получившие строки для равенства.

var obj1={test:"value"};
var obj2={test:"value2"};

alert(JSON.encode(obj1)===JSON.encode(obj2));

ПРИМЕЧАНИЕ: В то время как этот ответ будет работать во многих случаях, как несколько человек указали в комментариях, это проблематично по ряду причин. В в значительной степени всех случаях Вы захотите найти больше надежного решения.

47
ответ дан Joel Anair 23 May 2017 в 12:10
поделиться

Вы пытаетесь проверить, равны ли два объекта? то есть: их свойства равны?

Если это так, вы, вероятно, заметили эту ситуацию:

var a = { foo : "bar" };
var b = { foo : "bar" };
alert (a == b ? "Equal" : "Not equal");
// "Not equal"

вам, возможно, придется сделать что-то вроде этого:

function objectEquals(obj1, obj2) {
    for (var i in obj1) {
        if (obj1.hasOwnProperty(i)) {
            if (!obj2.hasOwnProperty(i)) return false;
            if (obj1[i] != obj2[i]) return false;
        }
    }
    for (var i in obj2) {
        if (obj2.hasOwnProperty(i)) {
            if (!obj1.hasOwnProperty(i)) return false;
            if (obj1[i] != obj2[i]) return false;
        }
    }
    return true;
}

Очевидно, что эта функция могла бы сделать с небольшим количеством оптимизации и способностью делать глубокую проверку (для обработки вложенных объектов: var a = { foo : { fu : "bar" } }), но вы поняли идею.

Как указывалось для FOR, вам, возможно, придется адаптировать это для ваших собственных целей, например: разные классы могут иметь разные определения «равных». Если вы просто работаете с простыми объектами, вышеописанного может быть достаточно, в противном случае можно воспользоваться пользовательской функцией MyClass.equals().

18
ответ дан nickf 23 May 2017 в 12:10
поделиться

Вот общая функция проверки равенства, которая получает массив элементов в качестве входных данных и сравнивает их друг с другом. Работает со всеми типами элементов.

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);
});

Существует также суть

0
ответ дан muratgozel 23 May 2017 в 12:10
поделиться

Зависит от того, что Вы подразумеваете под равенством. И поэтому Вам решать, как разработчик классов, для определения их равенства.

существует один случай, используемый иногда, где два экземпляра считают 'равными', если они указывают на то же местоположение в памяти, но это не всегда, что Вы хотите. Например, если у меня есть класс Человека, я мог бы хотеть считать два объекта Человека 'равными', если у них есть та же Фамилия, Имя и Номер социального страхования (даже если они указывают на различные местоположения в памяти).

, С другой стороны, мы не можем просто сказать, что два объекта равны, если значение каждого из их участников является тем же, с тех пор, иногда, Вы не хотите это. Другими словами, для каждого класса, это до разработчика класса для определения, какие участники составляют объекты 'идентификационные данные' и разрабатывают надлежащий оператор равенства (быть им через перегрузку ==, оператор или Равняется методу).

Высказывание, что два объекта равны, если у них есть тот же хеш, является одним выходом. Однако тогда необходимо задаться вопросом, как хеш вычисляется для каждого экземпляра. Возвращаясь к примеру Человека выше, мы могли использовать эту систему, если бы хеш был вычислен путем рассмотрения значений Имени, Фамилии и полей Social Security Number. Вдобавок ко всему, мы тогда полагаемся на качество метода хеширования (это - огромная тема самостоятельно, но достаточно сказать, что не все хеши создаются равные, и плохо хеширование методов может привести к [еще 110] коллизии, которые в этом случае возвратили бы ложные соответствия).

1
ответ дан FOR 23 May 2017 в 12:10
поделиться

Я не знаю, опубликовал ли кто-нибудь что-нибудь похожее на это, но вот функция, которую я сделал для проверки на предметное равенство.

function objectsAreEqual(a, b) {
  for (var prop in a) {
    if (a.hasOwnProperty(prop)) {
      if (b.hasOwnProperty(prop)) {
        if (typeof a[prop] === 'object') {
          if (!objectsAreEqual(a[prop], b[prop])) return false;
        } else {
          if (a[prop] !== b[prop]) return false;
        }
      } else {
        return false;
      }
    }
  }
  return true;
}

Кроме того, он рекурсивен, поэтому он также может проверять наличие глубокого равенства, если вы так его называете.

6
ответ дан Zac 23 May 2017 в 12:10
поделиться

Простейшие и логические решения для сравнения всего, например Object, Array, String, Int ...

JSON.stringify({a: val1}) === JSON.stringify({a: val2})

Примечание:

  • вам необходимо заменить val1 и val2 на ваш объект
  • для объекта, вы должны сортировать (по ключу) рекурсивно для обоих сторонних объектов
17
ответ дан Pratik Bhalodiya 23 May 2017 в 12:10
поделиться

Я бы посоветовал не использовать хэширование или сериализацию (как предлагает решение JSON). Если вам нужно проверить, равны ли два объекта, вам нужно определить, что означает «равно». Может случиться так, что все элементы данных в обоих объектах будут совпадать, или может случиться так, что ячейки памяти должны совпадать (имеется в виду, что обе переменные ссылаются на один и тот же объект в памяти), или может быть, что только один элемент данных в каждом объекте должен совпадать.

Недавно я разработал объект, конструктор которого создает новый идентификатор (начиная с 1 и увеличивая на 1) каждый раз, когда создается экземпляр. Этот объект имеет функцию isEqual, которая сравнивает это значение id со значением id другого объекта и возвращает true, если они совпадают.

В этом случае я определил «равно» как означающее, что значения идентификатора совпадают. Учитывая, что каждый экземпляр имеет уникальный идентификатор, это можно использовать для реализации идеи о том, что совпадающие объекты также занимают одно и то же место в памяти. Хотя в этом нет необходимости.

3
ответ дан Bernard Igiri 23 May 2017 в 12:10
поделиться

Моя версия, которая включает в себя цепочку, где находится разница, и в чем разница.

function DeepObjectCompare(O1, O2)
{
    try {
        DOC_Val(O1, O2, ['O1->O2', O1, O2]);
        return DOC_Val(O2, O1, ['O2->O1', O1, O2]);
    } catch(e) {
        console.log(e.Chain);
        throw(e);
    }
}
function DOC_Error(Reason, Chain, Val1, Val2)
{
    this.Reason=Reason;
    this.Chain=Chain;
    this.Val1=Val1;
    this.Val2=Val2;
}

function DOC_Val(Val1, Val2, Chain)
{
    function DoThrow(Reason, NewChain) { throw(new DOC_Error(Reason, NewChain!==undefined ? NewChain : Chain, Val1, Val2)); }

    if(typeof(Val1)!==typeof(Val2))
        return DoThrow('Type Mismatch');
    if(Val1===null || Val1===undefined)
        return Val1!==Val2 ? DoThrow('Null/undefined mismatch') : true;
    if(Val1.constructor!==Val2.constructor)
        return DoThrow('Constructor mismatch');
    switch(typeof(Val1))
    {
        case 'object':
            for(var m in Val1)
            {
                if(!Val1.hasOwnProperty(m))
                    continue;
                var CurChain=Chain.concat([m]);
                if(!Val2.hasOwnProperty(m))
                    return DoThrow('Val2 missing property', CurChain);
                DOC_Val(Val1[m], Val2[m], CurChain);
            }
            return true;
        case 'number':
            if(Number.isNaN(Val1))
                return !Number.isNaN(Val2) ? DoThrow('NaN mismatch') : true;
        case 'string':
        case 'boolean':
            return Val1!==Val2 ? DoThrow('Value mismatch') : true;
        case 'function':
            if(Val1.prototype!==Val2.prototype)
                return DoThrow('Prototype mismatch');
            if(Val1!==Val2)
                return DoThrow('Function mismatch');
            return true;
        default:
            return DoThrow('Val1 is unknown type');
    }
}
0
ответ дан Dakusan 23 May 2017 в 12:10
поделиться

ES6: минимальный код я мог сделать его, это. Это делает глубокое сравнение рекурсивно stringifying все объекты, единственное ограничение не является никакими методами, или символы, выдерживают сравнение.

const compareObjects = (a, b) => { 
  let s = (o) => Object.entries(o).sort().map(i => { 
     if(i[1] instanceof Object) i[1] = s(i[1]);
     return i 
  }) 
  return JSON.stringify(s(a)) === JSON.stringify(s(b))
}

console.log(compareObjects({b:4,a:{b:1}}, {a:{b:1},b:4}));
1
ответ дан Adriano Spadoni 4 November 2019 в 07:40
поделиться

Оператор равенства по умолчанию в JavaScript для объектов возвращает значение true, если они ссылаются на одно и то же место в памяти.

var x = {};
var y = {};
var z = x;

x === y; // => false
x === z; // => true

Если вам нужен другой оператор равенства, вам нужно добавить equals (other) или что-то в этом роде для ваших классов и специфика вашей проблемной области определят, что именно это означает.

Вот пример игральной карты:

function Card(rank, suit) {
  this.rank = rank;
  this.suit = suit;
  this.equals = function(other) {
     return other.rank == this.rank && other.suit == this.suit;
  };
}

var queenOfClubs = new Card(12, "C");
var kingOfSpades = new Card(13, "S");

queenOfClubs.equals(kingOfSpades); // => false
kingOfSpades.equals(new Card(13, "S")); // => true
148
ответ дан 22 November 2019 в 22:01
поделиться

Зачем изобретать колесо? Попробуйте Lodash. В нем есть ряд необходимых функций, таких как isEqual().

_.isEqual(object, other);

Он будет проверять каждое значение ключа методом перебора - как и другие примеры на этой странице - используя ECMAScript 5 и собственные оптимизации, если они доступны в браузере.

Примечание: Ранее в этом ответе рекомендовался Underscore.js, но lodash проделал лучшую работу по исправлению ошибок и решению проблем с согласованностью.

479
ответ дан 22 November 2019 в 22:01
поделиться

Нужна была более общая функция сравнения объектов, чем та, что была опубликована, и я придумал следующее. Критика приветствуется...

Object.prototype.equals = function(iObj) {
  if (this.constructor !== iObj.constructor)
    return false;
  var aMemberCount = 0;
  for (var a in this) {
    if (!this.hasOwnProperty(a))
      continue;
    if (typeof this[a] === 'object' && typeof iObj[a] === 'object' ? !this[a].equals(iObj[a]) : this[a] !== iObj[a])
      return false;
    ++aMemberCount;
  }
  for (var a in iObj)
    if (iObj.hasOwnProperty(a))
      --aMemberCount;
  return aMemberCount ? false : true;
}
3
ответ дан 22 November 2019 в 22:02
поделиться

Полезно считать два объекта равными, если они имеют одинаковые значения для всех свойств и рекурсивно для всех вложенных объектов и массивов. Я также считаю следующие два объекта равными:

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): Модульный тест и Средство выполнения тестов здесь .

2
ответ дан 22 November 2019 в 22:02
поделиться

Это - классический вопрос о JavaScript! Я создал метод для проверки глубокого объектного равенства с функцией способности выбрать свойства для игнорирования от сравнения. Аргументами являются два объекта выдержать сравнение, плюс, дополнительный массив stringified property-ignore относительный путь.

function isObjectEqual( o1, o2, ignorePropsArr=[]) {
    // Deep Clone objects
    let _obj1 = JSON.parse(JSON.stringify(o1)),
        _obj2 = JSON.parse(JSON.stringify(o2));
    // Remove props to ignore
    ignorePropsArr.map( p => { 
        eval('_obj1.'+p+' = _obj2.'+p+' = "IGNORED"');
    });
    // compare as strings
    let s1 = JSON.stringify(_obj1),
        s2 = JSON.stringify(_obj2);
    // return [s1==s2,s1,s2];
    return s1==s2;
}

// Objects 0 and 1 are exact equals
obj0 = { price: 66544.10, RSIs: [0.000432334, 0.00046531], candles: {A: 543, B: 321, C: 4322}}
obj1 = { price: 66544.10, RSIs: [0.000432334, 0.00046531], candles: {A: 543, B: 321, C: 4322}}
obj2 = { price: 66544.12, RSIs: [0.000432334, 0.00046531], candles: {A: 543, B: 321, C: 4322}}
obj3 = { price: 66544.13, RSIs: [0.000432334, 0.00046531], candles: {A: 541, B: 321, C: 4322}}
obj4 = { price: 66544.14, RSIs: [0.000432334, 0.00046530], candles: {A: 543, B: 321, C: 4322}}

isObjectEqual(obj0,obj1) // true
isObjectEqual(obj0,obj2) // false
isObjectEqual(obj0,obj2,['price']) // true
isObjectEqual(obj0,obj3,['price']) // false
isObjectEqual(obj0,obj3,['price','candles.A']) // true
isObjectEqual(obj0,obj4,['price','RSIs[1]'])   // true
0
ответ дан 22 November 2019 в 22:02
поделиться

Это - простая функция JavaScript для сравнения двух объектов, имеющих простые пары "ключ-значение". Функция возвратит массив строк, где каждая строка является путем к неравенству между двумя объектами.

function compare(a,b) {
    var paths = [];
    [...new Set(Object.keys(a).concat(Object.keys(b)))].forEach(key=>{
        if(typeof a[key] === 'object' && typeof b[key] === 'object') {
            var results = compare(a[key], b[key]);
            if(JSON.stringify(results)!=='[]') {
                paths.push(...results.map(result=>key.concat("=>"+result)));
            }
        }
        else if (a[key]!==b[key]) {
            paths.push(key);
        }
    })
    return paths;
}

, Если Вы только хотите сравнить два объекта, не зная пути к неравенствам, можно сделать это следующим образом:

if(JSON.stringify(compare(object1, object2))==='[]') {
   // the two objects are equal
} else {
   // the two objects are not equal
}
1
ответ дан 22 November 2019 в 22:02
поделиться
  1. сортируют объекты (словарь)
  2. , сравнивают строку JSON

    function areTwoDictsEqual(dictA, dictB) {
        function sortDict(dict) {
            var keys = Object.keys(dict);
            keys.sort();
    
            var newDict = {};
            for (var i=0; i<keys.length; i++) {
                var key = keys[i];
                var value = dict[key];
                newDict[key] = value;
            } 
            return newDict;
        }
    
        return JSON.stringify(sortDict(dictA)) == JSON.stringify(sortDict(dictB));
    }
    
0
ответ дан 22 November 2019 в 22:02
поделиться
const one={name:'mohit' , age:30};
//const two ={name:'mohit',age:30};
const two ={age:30,name:'mohit'};

function isEquivalent(a, b) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);



// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
    return false;
}

for (var i = 0; i < aProps.length; i++) {
    var propName = aProps[i];

    // If values of same property are not equal,
    // objects are not equivalent
    if (a[propName] !== b[propName]) {
        return false;
    }
}

// If we made it this far, objects
// are considered equivalent
return true;
}

console.log(isEquivalent(one,two))
0
ответ дан 22 November 2019 в 22:02
поделиться

После большой части поисков я нашел следующее рабочее решение

function isEquivalent(a, b) {
   // Create arrays of property names
   var aProps = Object.getOwnPropertyNames(a);
   var bProps = Object.getOwnPropertyNames(b);

  // If number of properties is different, objects are not equivalent
  if (aProps.length != bProps.length) {
     return false;
  }

  for (var i = 0; i < aProps.length; i++) {
     var propName = aProps[i];

    // If values of same property are not equal, objects are not equivalent
     if (a[propName] !== b[propName]) {
         return false;
     }
  }

// If we made it this far, objects are considered equivalent
return true; }

Для большего количества информации: Объектное Равенство в JavaScript

0
ответ дан 22 November 2019 в 22:02
поделиться

Мне нужно поднять запросы jQuery Post, поэтому равенство, которое имеет значение для меня, заключается в том, что оба объекта имеют одинаковый набор Свойства (нет отсутствует в любом объекте), и что каждое значение свойства «равно» (согласно этому определению). Мне все равно, что объекты, имеющие методы несоответствия.

Вот то, что я буду использовать, это должно быть достаточно хорошо для моих конкретных требованиях :

function PostRequest() {
    for (var i = 0; i < arguments.length; i += 2) {
        this[arguments[i]] = arguments[i+1];
    }

    var compare = function(u, v) {
        if (typeof(u) != typeof(v)) {
            return false;
        }

        var allkeys = {};
        for (var i in u) {
            allkeys[i] = 1;
        }
        for (var i in v) {
            allkeys[i] = 1;
        }
        for (var i in allkeys) {
            if (u.hasOwnProperty(i) != v.hasOwnProperty(i)) {
                if ((u.hasOwnProperty(i) && typeof(u[i]) == 'function') ||
                    (v.hasOwnProperty(i) && typeof(v[i]) == 'function')) {
                    continue;
                } else {
                    return false;
                }
            }
            if (typeof(u[i]) != typeof(v[i])) {
                return false;
            }
            if (typeof(u[i]) == 'object') {
                if (!compare(u[i], v[i])) {
                    return false;
                }
            } else {
                if (u[i] !== v[i]) {
                    return false;
                }
            }
        }

        return true;
    };

    this.equals = function(o) {
        return compare(this, o);
    };

    return this;
}

Использование так:

foo = new PostRequest('text', 'hello', 'html', '<p>hello</p>');
foo.equals({ html: '<p>hello</p>', text: 'hello' });
-1
ответ дан 22 November 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: