Pull to refresh

Comments 28

И еще
window.JSON = null;
var x = "(function () {alert('attack')})()"; // выполнится.
var y = function () {alert('attack')};

alert(jSonCmp(x,y))
Да ладно, даже
jSonCmp({a:1},{b:2})//=>true

Причина:
//ECMA Script standart check
isArray : function(obj) {
  return Object.prototype.toString.call(obj);
}
Поэтому и выложил, чтобы оттестировали. Ведь объектов много, а я один.
Если уж не TDD, то хотяб пару десятков тестов на, например, QUnit написать — минутное дело. При каждом изменении кода запускать — и нет таких нелепых ошибок.

Upd: А нет, вру, тесты есть. Но что такая банальщина не проходит — не понятно.
isArray подправил (вот что значит верстал в час ночи).

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

Насчёт выполнения javaScript-а — не очень уверен, что это проблема. Мы же эти данные не от пользователя получили.
Выполнение кода влечет нежелательные посторонние эффекты
window.JSON = null;
var x = "(function () {return 1})()";
var y = 1;

alert(jSonCmp(x,y)) // true


И дает разные результаты в средах, где есть windows.JSON и где его нет.

Мы же эти данные не от пользователя получили.
А кто вам такое сказал? В вашей исходной задаче эти данные как раз получаются от пользователя.

Посмотрел сравнение браузеров — да, действительно, от eval() можно смело отказываться — никто кроме IE7 с ним проблем не испытывает.

Кстати, аналогичным способом можно, получается, поломать и ext.JS-овский парсер JSON-а — там тоже eval() стоит.
А еще, свойства JavaScript объектов имеют порядок.

for(k in {a:1, b:2}) console.log(k);

a
b


for(k in {b:2, a:1}) console.log(k);


b
a
Я в требованиях это заявил — Равными должны считаться те объекты, у которых одинаковые поля содержат одинаковые значения. Порядок для объектов значения не имеет, он имеет значение для массивов.
Интересно, числа хранит упорядоченно:

for(k in {'b': 4, '999': 999, '2':2, 'a':'a', '1':3}) console.log(k);
1
2
999
b
a
Но заметьте, не в том порядке, который задали вы. Т.е. порядок элементов не гарантируется и зависит от реализации.
К примеру Chrome, Opera и IE10 ведут себя так, а FF и Safari 5, выводят в том же порядке:
for(k in {'b': 4, '999': 999, '2':2, 'a':'a', '1':3}) console.log(k);
b
999
2
a
1
А чем вас не устроил underscore и его isEqual? Там явно меньше ошибок. А библиотека весит не так и много. Ктому же, если испольуете extjs, То вообще не заметите прибавления в весе жсок.
Посмотрел underscore — алгоритм там такой же (добавлено разве что сравнение по конструкторам).

Но — не умеет «на лету» распаковывать JSON-ы, не сравнивает функции, нет поддержки jQuery объектов. Ну и array as set отсутствует.

Хотя вещь, конечно, тоже нужная.
Распаковывать на лету JSON, это задача другого уровня, а не алгоритма сравнения.
Если честно, мне трудно представить когда нужно сравнить объекты на равенство функций не по ссылке и инстансу, а по тексту.
var a = function(){};
var a1 = new a();
var a2 = new a();
_.isEqual(a1,a2); // true

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

Изобретение велосипедов вещь конечно интересная, но как правило за это приходится расплачиваться бОльшим кол-вом ошибок. И если велосипед не узкоспециализированный, то через продолжительное время становится выгонее выкинуть его, и использовать популярные библиотеки, т.к. они поддерживаются другими людми, в них намного чаще исправляются от ошибок, и не приходистя тратить время на утилиты, а с концентрироваться на основном функционале приложения.
Выгода-то как раз есть. Я узнал про underscore.js, а до этого узнал кучу всего об объектах в javaScript;.

Теперь если что-нибудь в underscore.js поломается, я смогу это починить.
Я не понимаю в чём проблема, ибо если порядок в множестве не важен, то можно сделать так:
var Compare = function(a, b){ for(i in a){ if(a[i] != b[i]){ return false;}} return true;};
Это будет примерно так:
var Compare = function(a, b){
	for(i in a){
		if(typeof(a[i]) == "object"){
			if(!Compare(a[i], b[i])){
				return false;
			}
		}else{
			if(a[i] != b[i]){
				return false;
			}
		}
	}
	return true;
};
У меня (и, как подсказывают, в underscore.js) так и сделано. Только прикручена защита от зацикливаний (мало ли, вдруг для сравнивания передадут уже созданные объекты, а там, в недрах, ссылка на parent) и сравнение не-объектных типов данных (вроде массивов).
Массивы — это объекты, числа и строки сравниваются оператором "==", а вот зацикливание реально надо проверять, спасибо!
Sign up to leave a comment.

Articles