{"id":983,"date":"2009-04-10T14:32:34","date_gmt":"2009-04-10T12:32:34","guid":{"rendered":"http:\/\/nyams.planbweb.com\/blog\/?p=983"},"modified":"2009-04-10T14:32:34","modified_gmt":"2009-04-10T12:32:34","slug":"comparaisons-dobjets-en-javascript","status":"publish","type":"post","link":"https:\/\/nyamsprod.com\/blog\/comparaisons-dobjets-en-javascript\/","title":{"rendered":"Comparaisons d&#8217;objets en javascript"},"content":{"rendered":"<div class=\"message warning\">\n<p><strong>Attention:<\/strong> Les informations de ce billet sont susceptibles d'&ecirc;tre obsol&egrave;tes car vieux de plus 2 ans.<\/p>\n<p><strong>Warning: <\/strong> The information you are reading may be obsolete, this post was published more than 2 years ago.<\/p>\n<\/div><p>Une des questions que j&#8217;aime \u00e0 poser aux\u00a0 jeunes d\u00e9veloppeurs qui viennent passer une interview d&#8217;embauche chez nous est <em>quelle est la diff\u00e9rence entre l&#8217;op\u00e9rateur (<code>==<\/code>) et l&#8217;op\u00e9rateur (<code>===<\/code>) <\/em>?. En <em>javascript<\/em> comme en <em>PHP<\/em>, la r\u00e9ponse et la m\u00eame le premier pratique une conversion silencieuse des valeurs que l&#8217;on compare tandis que l&#8217;autre ne le fait pas.<!--more--><br \/>\nDans un monde id\u00e9al <strong>on devrait donc toujours utiliser l&#8217;op\u00e9rateur <code>===<\/code> pour comparer 2 valeurs<\/strong>. Mais seulement voila essayer de comparer 2 objets en <em>javascript<\/em> en utilisant cet op\u00e9rateur et <a title=\"Op\u00e9rateurs de comparaison\" href=\"https:\/\/developer.mozilla.org\/fr\/R%C3%A9f%C3%A9rence_de_JavaScript_1.5_Core\/Op%C3%A9rateurs\/Op%C3%A9rateurs_de_comparaison\">vous aurez une petite surprise<\/a>. C&#8217;est simple, \u00e0 moins que les 2 objets fassent r\u00e9f\u00e9rence au m\u00eame objet l&#8217;op\u00e9rateur retournera syst\u00e9matiquement <code>false<\/code>. En d&#8217;autre terme, si comme moi vous d\u00e9sirez <strong>savoir si 2 objets distinctes sont similaires<\/strong> l&#8217;op\u00e9rateur <code>===<\/code> ne fonctionne pas, tout comme l&#8217;op\u00e9rateur <code>==<\/code> d&#8217;ailleurs.<br \/>\nVu qu&#8217;aucune solution <em>out of the box<\/em> existe en <code>javascript<\/code>, je me suis r\u00e9solu \u00e0 cr\u00e9er une fonction qui me permettrait de r\u00e9pondre \u00e0 ma question le plus facilement possible.<\/p>\n<p><strong>Pour que 2 objets soient similaires il faut que les m\u00e9thodes et les propri\u00e9t\u00e9s qu&#8217;ils contiennent soient identiques. <\/strong>Donc suivant tout b\u00eatement mon raisonnement je suis arrivait \u00e0 la fonction suivante:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">function isObjectsEquals(a, b) {\nvar isOK = true;\nfor (var prop in a) {\nif (a&#x5B;prop] !== b&#x5B;prop]) {\nisOK = false;\nbreak;\n}\n}\nreturn isOK;\n};<\/pre>\n<p>Ce code fonctionne mais il est trop incomplet. Disons-le clairement, je suis \u00e0 la recherche d&#8217;un code assez robuste pour pouvoir l&#8217;inclure dans ma librairie de fonctions que j&#8217;utilise dans mes projets <em>javascript<\/em>, je recherche donc une fonction <strong>bullet proof<\/strong>. D&#8217;o\u00f9, les optimisations que je lui est apport\u00e9es.<br \/>\nMa premi\u00e8re optimisation a \u00e9t\u00e9 de v\u00e9rifier <em>uniquement <\/em>les m\u00e9thodes r\u00e9ellement sp\u00e9cifique \u00e0 l&#8217;objet et non les m\u00e9thodes h\u00e9rit\u00e9es du fait que l&#8217;on utilise un objet. Je suis pass\u00e9 \u00e0 la fonction interm\u00e9diaire suivante :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">function isObjectsEquals(a, b) {\nvar isOK = true;\nfor (var prop in a) {\nif (a.hasOwnProperty(prop)) {\nif (a&#x5B;prop] !== b&#x5B;prop]) {\nisOK = false;\nbreak;\n}\n}\n}\nreturn isOK;\n};<\/pre>\n<p><em><a title=\"Conventions de bon codage en Javascript\" href=\"http:\/\/javascript.crockford.com\/code.html\">On devrait toujours utiliser<\/a> <code>hasOwnProperty<\/code> lorsque l&#8217;on boucle en javascript sur un objet, pour ceux qui ne le savent pas \ud83d\ude09 .<\/em><\/p>\n<p>L&#8217;optimisation suivante est en rapport avec la comparaison effectu\u00e9e \u00e0 l&#8217;int\u00e9rieur m\u00eame de ma fonction. Les plus perspicaces d&#8217;entre vous auront not\u00e9 que j&#8217;utilise <em>encore <\/em>un op\u00e9rateur de comparaison. Et donc je n&#8217;ai fait que d\u00e9plac\u00e9 le probl\u00e8me initial. Que se passerait-il si l&#8217;une des m\u00e9thode de mon objet \u00e9tait un objet en soit ? Tout ce travail n&#8217;aurez donc servi \u00e0 rien. Pour rem\u00e9dier \u00e0 cela il faudrait d\u00e9terminer le type des m\u00e9thodes de l&#8217;objet et au cas \u00e9ch\u00e9ant proc\u00e9der \u00e0 un appel r\u00e9cursif \u00e0 ma fonction.<br \/>\nSans aller dans les d\u00e9tails, il se trouve que l&#8217;utilisation des fonctions <a title=\"`instanceof` considered harmful (or how to write a robust `isArray`)\" href=\"http:\/\/thinkweb2.com\/projects\/prototype\/instanceof-considered-harmful-or-how-to-write-a-robust-isarray\/\"><code>typeof<\/code> et <code>instanceof<\/code> est d\u00e9conseill\u00e9e<\/a>, il faut plut\u00f4t se fier \u00e0 <code>Object.prototype.toString<\/code>, une propri\u00e9t\u00e9 interne de tout objet en <code>javascript<\/code>, pour d\u00e9terminer \u00e0 coup s\u00fbr le type d&#8217;une variable. De fait ma fonction finale ressemble \u00e0 ceci :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">function isObjectsEquals(a, b) {\nvar prop, otype, isOK = true;\nfor (prop in a) {\nif (a.hasOwnProperty(prop)) {\notype = Object.prototype.toString.call(a&#x5B;prop]).match(\/^&#x5B;objects(.*)]$\/)&#x5B;1];\nisOK\u00a0 = (!\/^(String|Number|Window)$\/.test(otype)) ? arguments.callee(a&#x5B;prop], b&#x5B;prop]) : (a&#x5B;prop] === b&#x5B;prop]);\nif (isOK !== true) {\nbreak;\n}\n}\n}\nreturn isOK;\n};<\/pre>\n<p>Et voila. Et comme cette fonction est toute jeune, si il y a parmi vous des volontaires pour la tester et pourquoi pas trouver des bugs pour l&#8217;am\u00e9liorer, je serais le premier ravi car pour l&#8217;instant elle fonctionne dans tous mes tests \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Comme il est impossible de comparer des objet de mani\u00e8re natif dans javascript voici, isObjectsEquals. Cette fonction va vous permettre de comparer des objets en javascript m\u00eame lorsque ceux-ci ne font pas r\u00e9f\u00e9rence au m\u00eame objet<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5],"tags":[42,116,244,284,292,397,405,531,542],"class_list":["post-983","post","type-post","status-publish","format-standard","hentry","category-web","tag-argumentscallee","tag-comparaison","tag-hasownproperty","tag-instanceof","tag-javascript","tag-objet","tag-operator","tag-tostring","tag-typeof"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/posts\/983","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/comments?post=983"}],"version-history":[{"count":0,"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/posts\/983\/revisions"}],"wp:attachment":[{"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/media?parent=983"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/categories?post=983"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nyamsprod.com\/blog\/wp-json\/wp\/v2\/tags?post=983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}