2009-12-18 8 views
31

Possible en double:
Are there legitimate uses for JavaScript’s “with” statement?"avec" mot-clé dans javascript

J'ai découvert récemment que le javascript, on peut faire quelque chose comme ce qui suit:

with document{ 
    write('foo'); 
    body.scrollTop = x; 
} 

L'inconvénient de ceci est que chaque variable doit être vérifiée pour voir si elle appartient à l'objet document, en créant un surcoût significatif.

Sinon, on pourrait faire quelque chose comme ceci:

var d = document; 
d.write('foo'); 
d.body.scrollTop = x; 

Existe-t-il des situations où l'utilisation du « avec » mot-clé est justifiée?

Répondre

12

Voici quelques messages de blog à l'appui du mot-clé avec. Mais s'il vous plaît lire l'entrée du blog YUI que azazul posté aussi bien!

http://webreflection.blogspot.com/2009/12/with-worlds-most-misunderstood.html http://webreflection.blogspot.com/2009/12/with-some-good-example.html

+0

@Abel, vous avez raison, cela répond à ma question gentiment ainsi que coller une mise en garde géante là-bas aussi. –

+3

@Annie: Je pense que vous devriez coller quelques citations ici au lieu de simplement relier deux articles connexes. Que se passe-t-il si elles conduisent à un code HTTP 404 (ou similaire) plus tard (par exemple parce que ces articles ont été déplacés/supprimés)? – Sk8erPeter

+1

** L'utilisation de 'with 'n'est pas recommandée et est interdite dans le mode strict d'ECMAScript 5. L'alternative recommandée est d'affecter l'objet dont vous voulez accéder aux propriétés à une variable temporaire. ** Source: [Mozilla Developer Network] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Déclarations/avec) – Pankaj

50

Il suffit de ne pas l'utiliser: http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/

déclaration JavaScript with a pour but de fournir un raccourci pour écrire les accès aux objets récurrents. Ainsi, au lieu d'écrire

ooo.eee.oo.ah_ah.ting.tang.walla.walla.bing = true; 
ooo.eee.oo.ah_ah.ting.tang.walla.walla.bang = true; 

Vous pouvez écrire

with (ooo.eee.oo.ah_ah.ting.tang.walla.walla) { 
    bing = true; 
    bang = true; 
} 

Cela ressemble beaucoup plus agréable. Sauf pour une chose. Il n'y a aucun moyen que vous pouvez dire en regardant le code bing et bang sera modifié. Est-ce que ooo.eee.oo.ah_ah.ting.tang.walla.walla sera modifié? Ou va les variables globales bing et bang? Il est impossible de savoir à coup sûr ...

Si vous ne pouvez pas lire un programme et être sûr que vous savez ce qu'il va faire, vous ne pouvez pas avoir confiance qu'il va fonctionner correctement. Pour cette raison, la déclaration with devrait être évité ...

+2

Je ne peux pas exprimer cela assez: toute syntaxe "avec", comme celle de JavaScript et Delphi, où vous ne spécifiez pas explicitement quels identifiants appartiennent à l'objet "scoped", et lesquels ne sont pas , sont ** mal **, n'utilisez pas cette syntaxe dans ces langues. En particulier, les changements futurs pourraient changer le comportement de ce code sans avertissement. Si ce n'est pas un bug qui n'attend que ça, alors je ne sais pas ce que c'est. –

+1

Par exemple, Visual Basic.NET a bien compris, http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx, où il vous force à préfixer tous les identifiants appartenant à l'objet étendu. avec un point. –

+0

Oui, VB (.NET et avant) l'a bien compris, mais ils se sont aussi trompés: si vous utilisez la liaison tardive, vous êtes toujours dans le même problème. Et les performances avec 'with' sont plus lentes que les autres (pour une raison étrange). – Abel

5

J'éviter d'utiliser dans le code de production, car il est ambigu, mais il existe une solution alternative à la boucle for fermeture solution en utilisant with pour imiter la let liaison, voici une copie de ma réponse précédente:

une alternative à la solution de fermeture standard en utilisant des fonctions à l'intérieur d'une boucle:

<a href="#">blah</a><br> 
<a href="#">blah</a><br> 
<a href="#">foo</a><br> 
<script> 
    (function() { 
    var anchors = document.getElementsByTagName('a'); 
     for (var i = anchors.length; i--;) { 
      var link = anchors[i]; 
      with ({ number: i }) { 
       link.onclick = function() { 
        alert(number); 
       }; 
      } 
     } 
    })(); 
</script> 

crédit nlogax pour fournir une solution que je à peu près arnaquer: Javascript infamous Loop issue?

Voici la solution standard:

<script> 
    (function() { 
    var anchors = document.getElementsByTagName('a'); 
    for (var i = anchors.length; i--;) { 
     var link = anchors[i]; 
     (function(i) { 
      link.onclick = function() { 
       alert(i) 
      } 
     })(i); 
    } 
    })(); 
</script> 
+2

Veuillez vous assurer que vous indiquez quelle partie est "ambiguë", car l'interpréteur JavaScript et/ou le compilateur ne sont jamais confus sur ce qu'il faut utiliser pour le identifiant. Ce sont les changements futurs et/ou ce qu'un programmeur peut interpréter comme un identifiant. –

12

Malgré les avis contraires presque partout, je pense qu'il ya des utilisations pour « avec ». Par exemple, je travaille sur une structure de modèle de domaine pour Javascript, qui utilise le caractère de soulignement de la même manière que jQuery utilise "$". Cela signifie que sans "avec", j'ai beaucoup de traits de soulignement dispersés dans mon code de manière à le rendre moins lisible. Voici une ligne au hasard à partir d'une application à l'aide du cadre:

_.People().sort(_.score(_.isa(_.Parent)),'Surname','Forename'); 

alors qu'avec « avec » il ressemblerait

with (_) { 
    ... 

    People().sort(score(isa(Parent)),'Surname','Forename'); 

    ... 
} 

Ce qui serait vraiment utile est une version en lecture seule de « avec ».

+0

Pas toujours l'exécution de SLOWER vous donne des effets secondaires. C'est négligeable si vous ne le faites pas mille fois. – kroe

+2

Ces jours-ci, avec la déstructuration d'objets ES6, vous pouvez faire 'const {People, score, isa, Parent} = _;', et ne pas apporter tous les méchants risques de 'with (_)'. –