¿Cuál es el propósito de la palabra clave var y cuándo debo usarla (u omitirla)?
NOTA : Esta pregunta se hizo desde el punto de vista de ECMAScript versión 3 o 5. Las respuestas pueden quedar obsoletas con la introducción de nuevas funciones en el lanzamiento de ECMAScript 6.
¿Cuál es exactamente la función de la var
palabra clave en JavaScript y cuál es la diferencia entre
var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;
y
someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;
?
¿Cuándo usarías cualquiera de ellos y por qué/para qué sirve?
Si estás en el ámbito global, entonces no hay mucha diferencia. Lea la respuesta de Kangax para obtener una explicación.
Si está en una función, var
creará una variable local, "no var" buscará en la cadena de alcance hasta que encuentre la variable o llegue al alcance global (en cuyo momento la creará):
// 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 no estás haciendo una tarea, entonces necesitas usar var
:
var x; // Declare x
Hay una diferencia .
var x = 1
declara una variable x
en el alcance actual (también conocido como contexto de ejecución). Si la declaración aparece en una función, se declara una variable local; si está en el ámbito global, se declara una variable global.
x = 1
, por el contrario, no es más que una cesión de propiedad. Primero intenta resolver x
contra la cadena de alcance. Si lo encuentra en algún lugar de esa cadena de alcance, realiza la asignación; si no lo encuentra x
, solo entonces crea x
una propiedad en un objeto global (que es un objeto de nivel superior en una cadena de alcance).
Ahora, observe que no declara una variable global, crea una propiedad global.
La diferencia entre los dos es sutil y puede resultar confusa a menos que comprenda que las declaraciones de variables también crean propiedades (solo en un objeto variable) y que cada propiedad en Javascript (bueno, ECMAScript) tiene ciertos indicadores que describen sus propiedades: ReadOnly, DontEnum y No eliminar.
Dado que la declaración de variable crea una propiedad con el indicador DontDelete, la diferencia entre var x = 1
y x = 1
(cuando se ejecuta en el ámbito global) es que la primera (declaración de variable) crea la propiedad DontDelete'able y la última no. Como consecuencia, la propiedad creada mediante esta asignación implícita se puede eliminar del objeto global, y la anterior, la creada mediante una declaración de variable, no se puede eliminar.
Pero esto es sólo teoría, por supuesto, y en la práctica hay aún más diferencias entre los dos , debido a varios errores en las implementaciones (como las de IE).
Espero que todo tenga sentido :)
[Actualización 16/12/2010]
En ES5 (ECMAScript 5; quinta edición del lenguaje recientemente estandarizada) existe el llamado "modo estricto", un modo de lenguaje opcional que cambia ligeramente el comportamiento de las asignaciones no declaradas. En modo estricto, la asignación a un identificador no declarado es un ReferenceError . La razón de esto era detectar asignaciones accidentales, evitando la creación de propiedades globales no deseadas. Algunos de los navegadores más nuevos ya han comenzado a admitir el modo estricto. Vea, por ejemplo, mi tabla de compatibilidad .
Decir que es la diferencia entre " local y global " no es del todo exacto.
Quizás sería mejor pensar en ello como la diferencia entre " local y más cercano ". Seguramente lo más cercano puede ser global, pero no siempre será así.
/* 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;
}
}