32 votes

Pourquoi ne puis-je pas utiliser une fonction Javascript avant sa définition dans un bloc try?

Comme expliqué ici, définitions de fonction peut être utilisé avant qu'ils ne soient définis. Mais dès qu'une section de code est enveloppé dans un bloc try, cela cesse d'être le cas.

Cela affiche "Hello world":

hello();
function hello() { alert("Hello world"); }

Mais cela affiche "ReferenceError: bonjour n'est pas défini":

try {
  hello();
  function hello() { alert("Hello world"); }
} catch (err) {
  alert(err);
}

Donc, il y a clairement quelque chose de "spécial" dans un bloc try concernant les déclarations de fonction. Est-il un moyen de contourner ce problème?

26voto

BGerrissen Points 9274

Firefox interprète les instructions de fonction différemment et, apparemment, ils ont cassé la déclaration de levage pour la déclaration de la fonction. ( Une bonne lecture sur les fonctions nommées / déclaration vs expression )

Pourquoi est-ce que Firefox interpréter des énoncés différemment, c'est parce que le code suivant:

if ( true ) {
    function test(){alert("YAY");}
} else {
    function test(){alert("FAIL");}
}
test(); // should alert FAIL

En raison de la déclaration de levage, la fonction test devrait toujours en alerte "échec", mais pas dans Firefox. Le code ci-dessus fait des alertes "YAY" dans Firefox et je soupçonne que le code qui fait qui arriver a finalement brisé la déclaration de levage tout à fait.

Je suppose que Firefox tourne les déclarations de fonction dans var déclarations lorsqu'ils sont situés dans le if/else ou les instructions try/catch. Comme suit:

// firefox interpretted code
var test; // hoisted
if (true) {
   test = function(){alert("yay")}
} else {
   test = function(){alert("fail")}
}

Après un bref débat avec Šime Vidas, je dois dire que Firefox ne traite qu'avec les déclarations de fonction est non-standard, en raison de:

La production SourceElement : Instruction est traitée pour la fonction les déclarations en ne prenant aucune mesure.
La production SourceElement : Déclaration est évaluée de la façon suivante:

  1. Évaluer Déclaration.
  2. Résultat De Retour(1).

Les deux FunctionDeclaration et de Déclaration sont SourceElements, ergo, il ne devrait pas être FunctionDeclarations à l'intérieur d'un énoncé (si/d'autre, try/catch). Donner Šime Vidas un brownie!

Try/catch est fondamentalement une autre forme de if/else et probablement utilise le même code d'exception.

5voto

Chris Noe Points 8375

Étant donné qu'un bloc fonction établit une portée locale avec référencement de fonction directe, l'encapsulation du contenu du bloc try dans une fonction immédiate semble restaurer ce comportement.

Cela fonctionne dans Firefox, IE, Chrome:

 try {
  (function(){
    hello();
    function hello() { alert("Hello world"); }
  }())
} catch (err) {
  alert(err);
}
 

Bien sûr, les fonctions et les variables définies dans la fonction try ne sont plus visibles dans le bloc catch, comme elles le seraient sans l'encapsuleur de fonction immédiat. Mais c'est une solution de contournement possible pour l'encapsulation de script try / catch.

1voto

sworoc Points 1078

Vous pouvez toujours le faire de cette façon et obtenir le meilleur des deux mondes:

function hello() {
  alert("Hello world");
}

try {
  hello();
}
catch (err) {
  alert(err);
}

Vous obtiendrez quand même des exceptions dans le bloc catch, mais la fonction sera disponible. Il devrait être plus facile à maintenir, et il n'y a pas de bénéfice fonctionnel pour le levage des fonctions de toute façon.

Edit:

Pour démontrer que c'est tout aussi durables que les enveloppant l'ensemble du code dans un try catch, je suis en fournissant un exemple plus détaillé.

function hello(str) {
  alert("Hello, " + str);
}

function greet() {
  asdf
}

try {
  var user = "Bob";
  hello(user);
  greet();
  asdf
}
catch (e) {
  alert(e);
}

Cela fonctionne comme prévu, aucune analyse de questions. Les seuls endroits où il risque d'échouer lors de temps de chargement sont à l'extérieur de la fonction defs et le try catch. Vous obtiendrez également des exceptions à toutes les ordures à l'intérieur de la fonction defs.

Je suppose que c'est un style de préférence, mais il semble être plus lisible et plus facile à gérer pour moi que les autres options.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X