119 votes

Fonction JavaScript ordre: pourquoi est-il important?

Question De Départ:

JSHint se plaint quand mon JavaScript appelle une fonction qui est définie en bas de la page de l'appel à elle. Cependant, ma page n'est pas un jeu, et pas de fonctions sont appelées jusqu'à ce que toute chose a téléchargé. Pourquoi donc l'ordre de fonctions apparaissent dans mon code la matière?

EDIT: je crois avoir trouvé la réponse.

http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

Je suis en train de gémir à l'intérieur. Semble que j'ai besoin de passer un AUTRE jour de re-commande de six mille lignes de code. La courbe d'apprentissage avec le javascript n'est pas raide du tout, mais il est très loooooong.

312voto

Zirak Points 13656

Edit: Pour un aperçu de ce qui couvre aussi certains ES6 déclarations (let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet

Cette étrange comportement dépend

  1. Comment vous définir les fonctions et les
  2. Lorsque vous les appelez.

Voici quelques exemples.

bar(); //This won't throw an error
function bar() {}

foo(); //This will throw an error
var foo = function() {}

----

bar();
function bar() {
    foo(); //This will throw an error
}
var foo = function() {}

----

bar();
function bar() {
    foo(); //This _won't_ throw an error
}
function foo() {}

---

function bar() {
    foo(); //no error
}
var foo = function() {}
bar();

C'est parce que de quelque chose qui s'appelle de levage!

Il y a deux façons de définir des fonctions: la Fonction de la déclaration et de la fonction de l'expression. La différence est ennuyeux, et de la minute, alors laissez-moi vous dire un peu de mal chose: Si vous avez écrit comme function name() {}, c'est une déclaration, et quand vous l'écrivez comme var name = function() {} (ou une fonction anonyme attribué à un retour, des choses comme ça), c'est une fonction d'expression.

Tout d'abord, examinons la manière dont les variables sont traitées:

var foo = 42;

//the interpreter turns it into this:
var foo;
foo = 42;

Maintenant, comment la fonction déclarations sont traitées:

var foo = 42;
function bar() {}

//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;

L' var états "jette" la création d' foo vers le très haut, mais ne pas attribuer de la valeur à l'instant. La déclaration de la fonction est la prochaine étape en ligne, et, finalement, d'une valeur est affectée à l' foo.

Et que dire de cela?

bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;

Seule la déclaration d' foo est déplacé vers le haut. La cession ne vient qu'après l'appel à l' bar est faite, où il était avant le levage s'est produite.

Et enfin, pour la concision:

bar();
function bar() {}
//turns to
function bar() {}
bar();

Maintenant, qu'en fonction d' expressions?

var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();

Comme des variables, la première foo est déclaré au point le plus élevé de la portée, puis il est affecté d'une valeur.

Voyons pourquoi le deuxième exemple renvoie une erreur.

bar();
function bar() {
    foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
    foo();
}
bar();
foo = function() {}

Comme nous l'avons vu auparavant, seule la création d' foo est hissé, la tâche vient où il est apparu dans les "originaux" (onu-hissés) du code. Lors de l' bar est appelé, il est avant foo est affectée une valeur, alors foo === undefined. Maintenant, dans la fonction-corps de bar, c'est comme si vous êtes en train de faire undefined(), ce qui déclenche une erreur.


tl;dr Si vous n'êtes pas à l'appel de rien jusqu'à ce que tout se charge, vous devriez être bien.

7voto

hugomg Points 29789

La principale raison en est probablement que JSLint n'seulement un laissez-passer sur le fichier afin qu'il ne sait pas qui vous permettra de définir une telle fonction;

Si vous avez utilisé les fonctions syntaxe de l'instruction

function foo(){ ... }

Il n'y a effectivement pas de différence à tous où que vous déclarez la fonction (il se comporte toujours comme si la déclaration est sur le debut)

D'autre part, si votre fonction a été définie comme un variable

var foo = function() { ... };

Vous avez pour vous garantir l'habitude de l'appeler avant l'initialisation. (cela peut effectivement être une source de bugs)


Depuis la réorganisation des tonnes de code est complexe et peut être une source de bugs en lui-même, je vous suggère de rechercher une solution de contournement. Je suis sûr que vous pouvez dire JSLint le nom des variables globales à l'avance afin de ne pas se plaindre non déclarées choses.

Mettre un commentaire sur le début du fichier

/*globals foo1 foo2 foo3*/

Ou vous pouvez utiliser une zone de texte là pour ça. (Je pense aussi que vous pouvez passer ce dans les arguments à l'intérieur jslint fonction si vous pouvez intervenir.)

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