2010-09-20 13 views
9

A veces voy a ver código como este:JavaScript creación de instancias de objetos

var Obj = Obj || {}; 

¿Qué hace esto? He tenido éxito escribiendo

array = array || []; 

Para crear una instancia de una matriz si no ya se ha creado una instancia, sin embargo, me gustaría saber un poco más sobre la mecánica de este.

+1

similar al operador C# '??', pero javascript lo hace sin definir un nuevo operador. http://msdn.microsoft.com/en-us/library/ms173224.aspx – lincolnk

Respuesta

11

La técnica trata de hacer uso de algo que se llama short circuit evaluation ... pero es complicado en Javascript, y resulta ser muy peligroso si se intenta hacer uso de ella para la creación de instancias de objetos.

La teoría detrás de la evaluación de cortocircuitos es que una declaración O solo se evalúa hasta el primer valor true. Por lo tanto, la segunda mitad de una declaración OR no se evalúa si la primera mitad es verdadera. Esto aplica a Javascript ......

Pero, las peculiaridades de Javascript, en particular cómo se manejan las variables no declaradas, hacen de esta una técnica que debe ser utilizada con sumo cuidado para crear instancias de objetos.

El siguiente código crea un objeto vacío, excepto si Obj fue declarado previamente en el mismo ámbito:

var Obj = Obj || {}; // Obj will now be {}, unless Obj was previously defined 
        // in this scope function.... that's not very useful... 

Esto es porque después var Obj, Obj estarán indefinidos a menos que se declaró en el mismo ámbito (incluidos siendo declarado como un parámetro para la función, si lo hay) ... así que {} será evaluado. (Link to an explanation of var en los comentarios de T.J. Crowder).

El siguiente código crea un objeto vacío sólo si Obj ha sido declarado previamente y ahora es Falsy:

Obj = Obj || {};  // Better make sure Obj has been previously declared. 

Si se utiliza la línea anterior, cuando Obj no se ha declarado previamente, habrá una error de tiempo de ejecución, ¡y el script se detendrá!

Por ejemplo, esto Javascript no evaluará en absoluto:

(function() { 
    Obj = Obj || "no Obj"; // error since Obj is undeclared JS cannot read from 
    alert(Obj);​   // an undeclared variable. (declared variables CAN 
})();      // be undefined.... for example "var Obj;" creates 
          // a declared but undefined variable. JS CAN try 
          // and read a declared but undefined variable) 

jsFiddle example

Pero esto Javascript siempre establece la Obj a "no Obj"!

var Obj ="I'm here!"; 
(function() { 
    var Obj = Obj || "no Obj"; // Obj becomes undefined after "var Obj"... 
    alert(Obj); // Output: "no Obj" 
})();​ 

jsFiddle example

Así que el uso de este tipo de evaluación de cortocircuito en Javascript es peligroso, ya que por lo general sólo se puede utilizar en forma

Obj = Obj || {}; 

Qué fallará precisamente cuando lo más deseable sería que funcione ... en el caso en que Obj no se declare.


Nota: que menciono esto en los comentarios de la penúltima ejemplo, pero es importante entender las 2 razones por las que una variable puede ser indefinido en Javascript.

  1. Una variable puede estar indefinida porque nunca fue declarada.
  2. Una variable no se puede definir porque se declaró pero no se le ha asignado un valor.

Una variable puede declararse utilizando la palabra clave var. Asignar un valor a una variable no declarada crea la variable.

Intentar utilizar una variable indefinida que también no se declara provoca un error de tiempo de ejecución. Usar una variable indefinida que ha sido declarada es perfectamente legal. Esta diferencia es lo que hace que el uso de Obj = Obj || {}; sea tan complicado, ya que no existe una forma significativa de la declaración anterior si Obj no está declarado O es una variable previamente existente.

+3

* "Si Obj ya existe, la evaluación de lo anterior se detendrá en var Obj = Obj" * Incorrecto en el caso normal. El hecho de que haya un 'var Obj' significa que para el momento el' Obj || {} 'parte de esa línea se evalúa (lo que sucede mucho después de que se maneje la parte' var Obj'), 'Obj' ** será ** indefinido, y por lo tanto no importa si hay un' Obj' en un contenido alcance. La única vez que esa declaración sería verdadera sería si hubiera * otro * 'var Obj' antes * dentro del mismo alcance * (función), lo cual es muy inusual. –

+0

@ T.J. Crowder: es precisamente para esos tiempos inusuales que esto es útil. El uso más común de esto sería establecer un valor predeterminado si el argumento 'Obj' no se pasa a una función - Eche un vistazo a estos 2 jsFiddles: http://jsfiddle.net/Ee7w3/ ---- http: //jsfiddle.net/34rbS/ –

+0

@Peter: la 'var' en esos violines no tiene ningún propósito en absoluto, y oscurece lo que realmente está sucediendo. Todavía estás modificando el argumento. http://jsbin.com/emulo/2 (¡No tratando de convertir esto en un jsbin vs. violín! ;-)) –

2
var Obj = Obj || {}; 

Creo que el var aquí no es necesario. Debe ser:

Obj = Obj || {}; 

Dónde Obj se define en otro lugar. Esto simplemente asignará Obj a un objeto vacío si es nulo o se va como está de no. También puede dejar la palabra clave var, en cuyo caso se asegurará de que el objeto se declare aunque no esté antes de esta declaración.

Lo mismo para la matriz: si es nula, la asignará a una matriz vacía.

3

La mecánica es un poco inusual: A diferencia de la mayoría de los idiomas, el operador de JavaScript || hace no retorno true o false. En cambio, devuelve el primer valor de "verdad" o el valor de la derecha. Por ejemplo:

alert("a" || "b");    // alerts "a", because non-blank strings are "truthy" 
alert(undefined || "b")   // alerts "b", because undefined is falsey 
alert(undefined || false || 0); // alerts "0", because while all are falsy, 0 is rightmost 

Más en this blog post.

Como Darin said, su var Obj = Obj || {}; probablemente no es una cita literal, más probablemente algo como esto:

function foo(param) { 
    param = param || {}; 
} 

... lo que significa, "si la persona que llama no me dio algo de Truthy param, el uso un objeto."

0

La clave para entender esta sintaxis es que el resultado de una expresión booleana o (o y) en JavaScript es el último componente evaluado. Como han señalado otros comentaristas, el cortocircuito de JavaScript se está utilizando junto con esta función para establecer condicionalmente el valor de array o Obj.

Obj = Obj || {}; 

Esto significa Obj se establece en el valor de la expresión Obj || {}.Si Obj es "verdadero", lo que significa que se evalúa como verdadero (para un objeto, esto significa que existe), el resultado de la expresión es Obj, porque la expresión cortocircuita. Sin embargo, si Obj es "falso" (inexistente), se debe evaluar la segunda parte de la expresión. Por lo tanto, en ese caso, el valor de la expresión es {}.

Cuestiones relacionadas