NOTE: Cette question a été posée du point de vue de la version 3 d'ECMAScript ou 5. Les réponses pourraient devenir obsolètes avec l’introduction de nouvelles fonctionnalités dans la version d’ECMAScript 6.
Quelle est exactement la fonction du mot clé var
en JavaScript et quelle est la différence entre
var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;
et
someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;
?
Quand utiliseriez-vous l'un ou l'autre, et pourquoi/que fait-il?
Si vous êtes dans le monde entier, il n'y a pas beaucoup de différence. Lire Kangax réponse pour explication
Si vous êtes dans une fonction, alors var
créera une variable locale, "no var" recherchera la chaîne de portées jusqu'à ce qu'elle trouve la variable ou atteigne la portée globale pointez il va le créer):
// These are both globals
var foo = 1;
bar = 2;
function()
{
var foo = 1; // Local
bar = 2; // Global
// Execute an anonymous function
(function()
{
var wibble = 1; // Local
foo = 2; // Inherits from scope above (creating a closure)
moo = 3; // Global
}())
}
Si vous ne faites pas d'affectation, vous devez utiliser var
:
var x; // Declare x
Il y a une différence .
var x = 1
déclare la variable x
dans la portée actuelle (ou contexte d'exécution). Si la déclaration apparaît dans une fonction - une variable locale est déclarée; si c'est dans la portée globale - une variable globale est déclarée.
x = 1
, d'autre part, est simplement une cession de propriété. Il essaie d’abord de résoudre x
contre la chaîne d’étendue. S'il le trouve n'importe où dans cette chaîne d'étendue, il effectue une affectation. si elle ne trouve pas x
, alors seulement elle crée la propriété x
sur un objet global (qui est un top objet de niveau dans une chaîne d'étendue).
Notez maintenant qu'il ne déclare pas de variable globale, il crée une propriété globale.
La différence entre les deux est subtile et peut prêter à confusion à moins de comprendre que les déclarations de variable créent également des propriétés (uniquement sur un objet Variable) et que chaque propriété de Javascript (bien, ECMAScript) ont certains drapeaux qui décrivent leurs propriétés - ReadOnly, DontEnum et DontDelete.
Puisque la déclaration de variable crée une propriété avec l’indicateur DontDelete, la différence entre var x = 1
et x = 1
(lorsqu’elle est exécutée dans une portée globale) est que l’ancienne - déclaration de variable - crée la propriété DontDelete'able, et la dernière ne le fait pas En conséquence, la propriété créée via cette affectation implicite peut ensuite être supprimée de l'objet global et l'ancien objet, celui créé via la déclaration de variable, ne peut pas être supprimé.
Mais ceci n’est que théorie, bien sûr, et dans la pratique, il existe encore plus de différences entre les deux , en raison de divers bugs dans les implémentations (telles que celles de IE ).
J'espère que tout a du sens :)
[Mise à jour 2010/12/16]
Dans ES5 (ECMAScript 5; 5ème édition du langage récemment normalisée), il existe un "mode strict" - un mode de langage opt-in, qui modifie légèrement le comportement des assignations non déclarées. En mode strict, l'affectation à un identifiant non déclaré est une erreur de référence (== --- ==) . La raison en était d’attraper les assignations accidentelles, empêchant la création de propriétés globales non désirées. Certains des nouveaux navigateurs ont déjà commencé à prendre en charge le mode strict. Voir, par exemple, ma table compat .
Dire que c'est la différence entre "local et global" n'est pas tout à fait exact.
Il serait peut-être préférable de penser à cela comme la différence entre "local et le plus proche". Le plus proche peut sûrement être mondial, mais ce ne sera pas toujours le cas.
/* global scope */
var local = true;
var global = true;
function outer() {
/* local scope */
var local = true;
var global = false;
/* nearest scope = outer */
local = !global;
function inner() {
/* nearest scope = outer */
local = false;
global = false;
/* nearest scope = undefined */
/* defaults to defining a global */
public = global;
}
}
Lorsque Javascript est exécuté dans un navigateur, tout votre code est entouré d'une instruction with, comme ceci:
with (window) {
//Your code
}
Plus d'infos sur with
- MDN
Puisque var
déclare une variable dans la portée actuelle , il n'y a pas de différence entre déclarer var
à l'intérieur de la fenêtre et ne pas le déclarer du tout.
La différence vient lorsque vous n'êtes pas directement à l'intérieur de la fenêtre, par exemple. à l'intérieur d'une fonction ou à l'intérieur d'un bloc.
Utiliser var
vous permet de masquer les variables externes portant le même nom. De cette façon, vous pouvez simuler une variable "privée", mais c'est un autre sujet.
Une règle empirique consiste à toujours utiliser var
, car vous risqueriez sinon d'introduire des bogues subtils.
EDIT: Après les critiques que j'ai reçues, je voudrais souligner les points suivants:
var
déclare une variable dans la portée actuelle window
var
déclare implicitement var
dans la portée globale (fenêtre)var
revient à l'omettre.var
n'est pas la même chose que de déclarer une variable sans var
var
explicitement car c'est une bonne pratiqueVous devez toujours utiliser le mot clé var
pour déclarer des variables. Pourquoi? Une bonne pratique de codage devrait être une raison suffisante en soi, mais déclarer une variable sans le mot clé var
signifie que cette dernière est déclarée dans la portée globale (une variable comme celle-ci s'appelle un global "implicite"). Douglas Crockford recommande de ne jamais utiliser de globes implicites , et conformément aux directives de codage JavaScript d'Apple :
Toute variable créée sans le mot clé
var
est créée à l’étendue globale et ne fait pas l’objet d’une ordure lors du retour de la fonction (car elle n’est pas hors de portée), ce qui présente l’occasion d’une fuite de mémoire.
En résumé, déclarez toujours les variables à l’aide du mot clé var
.
Voici un bon exemple de la façon dont vous pouvez être surpris en évitant de déclarer des variables locales avec var
:
<script>
one();
function one()
{
for (i = 0;i < 10;i++)
{
two();
alert(i);
}
}
function two()
{
i = 1;
}
</script>
(i
est réinitialisé à chaque itération de la boucle, car il n'est pas déclaré localement dans la boucle for
mais globalement), ce qui aboutit à une boucle infinie
Je dirais qu'il vaut mieux utiliser var
dans la plupart des situations.
Les variables locales sont toujours plus rapides que les variables de portée globale.
Si vous n'utilisez pas var
pour déclarer une variable, celle-ci aura une portée globale.
Pour plus d'informations, vous pouvez lancer une recherche sur "Chaîne d'étendue JavaScript" dans Google.
var
!var
était la manière pré-ES6 de déclarer une variable. Nous sommes maintenant dans le futur, et vous devriez coder en tant que tel.
const
et let
const
doit être utilisé dans 95% des cas. Cela fait en sorte que la référence de variable ne puisse pas changer, ainsi les propriétés de tableau, d'objet et de nœud DOM peuvent changer et devraient probablement être const
.
let
devrait être utilisé pour toute variable devant être réaffectée. Cela inclut dans une boucle for. Si vous écrivez déjà varName =
au-delà de l'initialisation, utilisez let
.
Les deux ont une portée au niveau du bloc, comme prévu dans la plupart des autres langues.
Sans var
- variable globale.
Fortement recommandé de TOUJOURS utiliser l'instruction var
, car init variable globale dans un contexte local - est mauvais. Mais, si vous avez besoin de ce sale tour, vous devriez écrire un commentaire au début de la page:
/* global: varname1, varname2... */
une autre différence, par exemple
var a = a || [] ; // works
tandis que
a = a || [] ; // a is undefined error.
L'utilisation de var
est toujours une bonne idée pour éviter que les variables n'encombrent la portée globale et que les variables n'entrent en conflit, ce qui entraîne un écrasement indésirable.
@Chris S a donné un bel exemple illustrant la différence pratique (et le danger) entre var
et non var
. En voici un autre. Je trouve celui-ci particulièrement dangereux car la différence n'est visible que dans un environnement asynchrone, de sorte qu'elle peut facilement passer inaperçue lors des tests.
Comme vous vous en doutez, les extraits de code suivants ["text"]
:
function var_fun() {
let array = []
array.Push('text')
return array
}
console.log(var_fun())
L'extrait suivant fait de même (notez le let
manquant avant array
):
function var_fun() {
array = []
array.Push('text')
return array
}
console.log(var_fun())
L'exécution asynchrone de la manipulation des données produit toujours le même résultat avec un seul exécuteur:
function var_fun() {
array = [];
return new Promise(resolve => resolve()).then(() => {
array.Push('text')
return array
})
}
var_fun().then(result => {console.log(result)})
Mais se comporte différemment avec plusieurs:
function var_fun() {
array = [];
return new Promise(resolve => resolve()).then(() => {
array.Push('text')
return array
})
}
[1,2,3].forEach(i => {
var_fun().then(result => {console.log(result)})
})
Utilisant laisser cependant:
function var_fun() {
let array = [];
return new Promise(resolve => resolve()).then(() => {
array.Push('text')
return array
})
}
[1,2,3].forEach(i => {
var_fun().then(result => {console.log(result)})
})
Voici un exemple de code que j'ai écrit pour que vous compreniez ce concept:
var foo = 5;
bar = 2;
fooba = 3;
// Execute an anonymous function
(function() {
bar = 100; //overwrites global scope bar
var foo = 4; //a new foo variable is created in this' function's scope
var fooba = 900; //same as above
document.write(foo); //prints 4
document.write(bar); //prints 100
document.write(fooba); //prints 900
})();
document.write('<br/>');
document.write('<br/>');
document.write(foo); //prints 5
document.write(bar); //prints 100
document.write(fooba); //prints 3
Je vois des gens confus lors de la déclaration de variables avec ou sans var et à l'intérieur ou à l'extérieur de la fonction. Voici un exemple profond qui vous guidera à travers ces étapes:
Voir le script ci-dessous en action ici à jsfiddle
a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");
function testVar1(){
c = 1;// Defined inside the function without var
var d = 1;// Defined inside the function with var
alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
a = a + 5;
b = b + 5;
c = c + 5;
d = d + 5;
alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};
testVar1();
alert("Run the 1. function again...");
testVar1();
function testVar2(){
var d = 1;// Defined inside the function with var
alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
a = a + 5;
b = b + 5;
c = c + 5;
d = d + 5;
alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};
testVar2();
alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);
Conclusion
- Quel que soit le sujet déclaré avec ou sans var (comme a, b), s’ils obtiennent leur valeur en dehors de la fonction, ils conservent leur valeur et toutes les autres valeurs ajoutées dans diverses fonctions par le biais du script sont préservées.
- Si la variable est déclarée sans var dans une fonction (comme c), elle agira comme la règle précédente, elle conservera désormais sa valeur dans toutes les fonctions. Soit il a obtenu sa première valeur dans la fonction testVar1 (), il conserve toujours la valeur et obtient une valeur supplémentaire dans la fonction testVar2 ()
- Si la variable est déclarée avec var dans une fonction uniquement (comme d dans testVar1 ou testVar2), elle sera indéfinie à la fin de la fonction. Donc ce sera une variable temporaire dans une fonction.
Dans un code, si vous utilisez une variable sans utiliser var, alors ce qui se passe est que var nom_var est automatiquement placé dans la portée globale, par exemple:
someFunction() {
var a = some_value; /*a has local scope and it cannot be accessed when this
function is not active*/
b = a; /*here it places "var b" at top of script i.e. gives b global scope or
uses already defined global variable b */
}
En tant que quelqu'un essayant d'apprendre ceci, c'est comme ça que je le vois. Les exemples ci-dessus étaient peut-être un peu trop compliqués pour un débutant.
Si vous exécutez ce code:
var local = true;
var global = true;
function test(){
var local = false;
var global = false;
console.log(local)
console.log(global)
}
test();
console.log(local);
console.log(global);
La sortie se lira comme suit: false, false, true, true
Parce qu'elle considère que les variables de la fonction sont séparées de celles qui se trouvent en dehors de celle-ci, d'où le terme variable locale, c'est parce que nous avons utilisé var dans l'affectation. Si vous supprimez la var dans la fonction, elle se lit maintenant comme ceci:
var local = true;
var global = true;
function test(){
local = false;
global = false;
console.log(local)
console.log(global)
}
test();
console.log(local);
console.log(global);
La sortie est fausse, fausse, fausse, fausse
En effet, plutôt que de créer une nouvelle variable dans la portée ou la fonction locale, elle utilise simplement les variables globales et les réaffecte à false.
Vous devez utiliser le mot-clé var sauf si vous avez l'intention d'associer la variable à l'objet window dans le navigateur. Voici un lien qui explique la portée et la différence entre la portée glocal et la portée locale avec et sans mot clé var.
Lorsque les variables sont définies sans utiliser le mot-clé var, il s’agit d’une simple opération "d’affectation".
Lorsque la valeur est affectée à une variable en javascript, l'interpréteur essaie d'abord de trouver la "déclaration de variable" dans le même contexte/la même portée que celui de l'affectation. Lorsque l'interprète exécute dummyVariable = 20
, il recherche la déclaration de dummyVariable au début de la fonction. (Puisque toutes les déclarations de variable sont déplacées au début du contexte par un interpréteur javascript, on parle de levage)
Vous voudrez peut-être aussi regarder levage en javascript
Sans utiliser "var", les variables ne peuvent définir que lorsqu'une valeur est définie. Par exemple:
my_var;
ne peut pas fonctionner dans portée globale ou toute autre portée. Il devrait être avec une valeur comme:
my_var = "value";
D'autre part, vous pouvez définir un vaiable comme;
var my_var;
Sa valeur est undefined
(sa valeur n'est pas null
et elle n'est pas égale à null
de manière intéressante.).