Równość obiektów jQuery

151

Jak sprawdzić, czy dwa obiekty jQuery są równe? Chciałbym mieć możliwość przeszukiwania tablicy dla konkretnego obiektu jQuery.

$.inArray(jqobj, my_array);//-1    
alert($("#deviceTypeRoot") == $("#deviceTypeRoot"));//False
alert($("#deviceTypeRoot") === $("#deviceTypeRoot"));//False
Casebash
źródło

Odpowiedzi:

225

Od wersji jQuery 1.6 możesz używać .is. Poniżej odpowiedź sprzed ponad roku ...

var a = $('#foo');
var b = a;


if (a.is(b)) {
    // the same object!
}

Jeśli chcesz sprawdzić, czy dwie zmienne są w rzeczywistości tym samym obiektem, np:

var a = $('#foo');
var b = a;

... wtedy możesz sprawdzić ich unikalne identyfikatory. Za każdym razem, gdy tworzysz nowy obiekt jQuery, otrzymuje on identyfikator.

if ($.data(a) == $.data(b)) {
    // the same object!
}

Chociaż to samo można osiągnąć za pomocą prostego a === b, powyższe może przynajmniej pokazać następnemu programistowi dokładnie, do czego testujesz.

W każdym razie prawdopodobnie nie o to ci chodzi. Jeśli chcesz sprawdzić, czy dwa różne obiekty jQuery zawierają ten sam zestaw elementów, możesz użyć tego:

$.fn.equals = function(compareTo) {
  if (!compareTo || this.length != compareTo.length) {
    return false;
  }
  for (var i = 0; i < this.length; ++i) {
    if (this[i] !== compareTo[i]) {
      return false;
    }
  }
  return true;
};

Źródło

var a = $('p');
var b = $('p');
if (a.equals(b)) {
    // same set
}
nickf
źródło
To rozwiązanie jest uproszczone do tego, które podaje phpdeveloper, gdy jest tylko jeden element. Innym sensem, w jakim obiekty jQuery można uznać za równe, jest to, czy mają ten sam selektor i kontekst. Jest to dość łatwe do testu: A.selector === B.selector && A.context === B.context. Często kontekst będzie zawsze ten sam, więc musimy tylko wziąć pod uwagę selektor.
Casebash,
2
@Casebash - prawda, jednak weź pod uwagę, że kilka selektorów może skończyć z tym samym zestawem wyników, np .: $(':first')i$('*:first')
nickf.
3
Uwaga @rampion i nickf, jQuery is () nie sprawdza, czy selektory są identyczne , a jedynie, czy się pokrywają. Świadek: jsfiddle.net/bnhkm/1
Bob Stein
Twoja equalsfunkcja wydaje się być wrażliwa na kolejność. coś takiego jak stackoverflow.com/a/29648479 działałoby w większej liczbie przypadków, chociaż jest wolniejsze.
Jayen
funkcja równości działa tylko wtedy, gdy obiekt ma jeden poziom! porównywanie a = b = [{dir: 'test', sort: [{test: {test: 1}}]}] nie działa
David Dunham
16

Jeśli nadal nie wiesz, możesz odzyskać oryginalny obiekt poprzez:

alert($("#deviceTypeRoot")[0] == $("#deviceTypeRoot")[0]); //True
alert($("#deviceTypeRoot")[0] === $("#deviceTypeRoot")[0]);//True

ponieważ $("#deviceTypeRoot")również zwraca tablicę obiektów, które wybrał selektor.

Mauris
źródło
1
Zostaną wyświetlone dwa alerty true, ponieważ porównujesz odniesienie do elementu DOM, ==a ===dadzą Ci te same wyniki (nie jest wymagane wymuszanie typu, są to tylko dwa odwołania do obiektów)
CMS,
Twoje drugie stwierdzenie w rzeczywistości zwraca Prawdę
Casebash,
a tak, to prawda. skopiuj i wklej błąd = D
mauris
14

$.fn.equals(...)Rozwiązaniem jest prawdopodobnie najczystszym i najbardziej elegancki jeden.

Próbowałem czegoś tak szybkiego i brudnego:

JSON.stringify(a) == JSON.stringify(b)

Prawdopodobnie jest drogie, ale wygodną rzeczą jest to, że jest niejawnie rekurencyjna, podczas gdy eleganckie rozwiązanie nie.

Tylko moje 2 centy.

Roberto Pierpaoli
źródło
1
to nie jest dobre do sprawdzania równości między dwoma obiektami jQuery, ale dla standardowych obiektów. takie jak „{a: 'x', b: 'y', c: 'z'} == {a: 'x', b: 'y', c: 'z'}". zastanawiam się, że nie ma jQuery.isEqual (a, b) ...
iRaS
13
To jest źle. Kolejność właściwości obiektu ma znaczenie. Więc jeśli masz {a: 1, b: 2}i {b: 2, a: 1}to wróci, falsegdy powinno wrócić true.
Eric Alberson
3
@EricAlberson, czy masz jakieś sugestie dotyczące innych narzędzi do głębokiego porównywania lub skryptów, które mogłyby poradzić sobie z tą sytuacją?
Neil Monroe
8

Ogólnie rzecz biorąc, złym pomysłem jest porównywanie $ (foo) z $ (foo), ponieważ jest to równoważne funkcjonalnie następującemu porównaniu:

<html>
<head>
<script language='javascript'>
    function foo(bar) {
        return ({ "object": bar });
    }

    $ = foo;

    if ( $("a") == $("a") ) {
        alert ("JS engine screw-up");
    }
    else {
        alert ("Expected result");
    }

</script>

</head>
</html>

Oczywiście nigdy nie spodziewałbyś się "spieprzenia silnika JS". Używam „$” tylko po to, aby wyjaśnić, co robi jQuery.

Za każdym razem, gdy wywołujesz $ ("# foo"), faktycznie wykonujesz jQuery ("# ​​foo"), które zwraca nowy obiekt . Zatem porównywanie ich i oczekiwanie tego samego przedmiotu nie jest poprawne.

Jednak MOŻESZ zrobić coś takiego:

<html>
<head>
<script language='javascript'>
    function foo(bar) {
        return ({ "object": bar });
    }

    $ = foo;

    if ( $("a").object == $("a").object ) {
        alert ("Yep! Now it works");
    }
    else {
        alert ("This should not happen");
    }

</script>

</head>
</html>

Więc naprawdę powinieneś porównać elementy ID obiektów jQuery w swoim prawdziwym programie, więc coś w stylu

... 
$(someIdSelector).attr("id") == $(someOtherIdSelector).attr("id")

jest bardziej odpowiednie.

Elf King
źródło
1
Żeby było jasne, jQuery nie ma atrybutu obiektu. Elf King wydaje się używać tego jako pseudokodu
Casebash,
4

Najpierw zamów obiekt na podstawie klucza, używając tej funkcji

function sortObject(o) {
    return Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {});
}

Następnie porównaj zmienną wersję swojego obiektu, używając tej funkcji

function isEqualObject(a,b){
    return JSON.stringify(sortObject(a)) == JSON.stringify(sortObject(b));
}

Oto przykład

Zakładając, że klucze obiektów są uporządkowane w różny sposób i mają te same wartości

var obj1 = {"hello":"hi","world":"earth"}
var obj2 = {"world":"earth","hello":"hi"}

isEqualObject(obj1,obj2);//returns true
Kareem
źródło
-1

Jeśli chcesz sprawdzić, czy zawartość jest równa, czy nie, po prostu użyj JSON.stringify (obj)

Np. - var a = {klucz: val};

var b = {klucz: wart};

JSON.stringify (a) == JSON.stringify (b) -----> Jeśli zawartość jest taka sama, otrzymasz wartość true.

Vikram
źródło
Najpierw musisz posortować klucze, jak odpowiedź Kareema
reggaeguitar