2009-10-21 11 views
38

He leído que en lugar de simplemente escribir un montón de funciones, debería usar el literal del objeto.JavaScript - Ventajas del objeto literal

¿Puede alguien explicar cuáles son las ventajas del objeto literal con ejemplos, porque no entiendo hasta ahora.

Gracias

Respuesta

64

Como dijo Russ Cam, se evita contaminar el espacio de nombres global, lo cual es muy importante en estos días de la combinación de secuencias de comandos desde múltiples ubicaciones (TinyMCE, etc.)

Como dijo Alex Sexton, también es una buena organización de código.

Si está utilizando esta técnica, le sugiero que utilice el patrón del módulo. Esto sigue utilizando objetos literales, pero a medida que el valor de retorno de una función de alcance:

var MyThingy = (function() { 

    function doSomethingCool() { 
     ... 
    } 

    function internalSomething() { 
     .... 
    } 

    function anotherNiftyThing() { 
     // Note that within the scoping function, functions can 
     // call each other direct. 
     doSomethingCool(); 
     internalSomething(); 
    } 

    return { 
     doSomethingCool: doSomethingCool, 
     anotherNiftyThing: anotherNiftyThing 
    }; 
})(); 

Uso externo:

MyThingy.doSomethingCool(); 

La función de alcance se envuelve alrededor de todas sus funciones, y luego te llaman de inmediato y almacena su valor de retorno. Ventajas:

  • funciones se declaran normalmente y por lo tanto tienen nombres . (Mientras que con el formato {name: function() { ... }}, todas sus funciones son anónimas, aunque las propiedades que las mencionan tienen nombres). Las herramientas de ayuda de nombres lo ayudan a mostrarle las pilas de llamadas en un depurador y decirle qué función arrojó una excepción. (Actualización de 2015: la última especificación de JavaScript, ECMAScript 6ª edición, define un gran número de formas en que el motor JavaScript debe infer nombre de una función. Una de ellas es cuando la función se asigna a una propiedad como en nuestro ejemplo {name: function() { ... }}. los motores implementan ES6, este motivo desaparecerá.)
  • Le da la libertad de tener funciones privadas solo utilizadas por su módulo (como mi internalSomething anterior). Ningún otro código en la página puede llamar a esas funciones; son verdaderamente privados. Solo los que exporta al final, en la declaración de devolución, son visibles fuera de la función de alcance.
  • Facilita la devolución de diferentes funciones dependiendo del entorno, si la implementación simplemente cambia completamente (como IE-vs-W3C, o SVG vs. Canvas, etc.).

Ejemplo de volver diferentes funciones:

var MyUtils = (function() { 
    function hookViaAttach(element, eventName, handler) { 
     element.attachEvent('on' + eventName, handler); 
    } 

    function hookViaListener(element, eventName, handler) { 
     element.addEventListener(eventName, handler, false); 
    } 

    return { 
     hook: window.attachEvent ? hookViaAttach : hookViaListener 
    }; 
})(); 

MyUtils.hook(document.getElementById('foo'), 'click', /* handler goes here */); 
+2

Cuando crea una instancia de la forma "anónima", aún puede darle un nombre (var x = function x() {...}). Cuando haces eso, el nombre está vinculado de modo que esté disponible para referencias recursivas dentro de la función. – Pointy

+1

@Pointy: no se puede hacer eso (usar un nombre de función dentro de una tarea) entre navegadores, no funciona correctamente en IE o Safari; detalles: http://yura.thinkweb2.com/named-function-expressions/ Y no es necesario, el nombre propio de la función (el 'foo' en' función foo') está dentro del alcance en todo el alcance donde se declara, incluso dentro de la función misma, para que 'foo' pueda llamarse a sí mismo a través del símbolo' foo', sin necesidad de asignar la referencia de función a nada (en ese punto). –

+0

(Continuación) De acuerdo, sería * agradable * poder usar la asignación y el nombre propio al mismo tiempo, ya que facilitaría la exportación de funciones desde la función de alcance. La especificación ciertamente lo permite, pero lamentablemente, los aspectos prácticos (errores de implementación) entran en él. –

15

Uso de un objeto literal (también conocido como modelo objeto literal) no van a contaminar el espacio de nombres global tan severamente como el uso de muchas funciones declaradas a nivel mundial lo hará, y también ayuda a organizar el código de una manera lógica

Para ejemplo, este objeto literal

var obj = { 
       find : function(elem) { /* find code */ }, 
       doSomething: function() { /* doSomething code */ }, 
       doSomethingElse: function() { /* doSomethingElse code */ } 
      } 

comparación con

function find(elem) { /* find code */ }, 
function doSomething() { /* doSomething code */ }, 
function doSomethingElse() { /* doSomethingElse code */ } 

creará una sola propiedad en el objeto global en comparación con tres. A continuación, puede utilizar simplemente las funciones como tal

obj.doSomething(); 
+2

puede escribir muchas funciones en una función normal y no contaminar su código. objeto literal no da ningún valor agregado. Yo mismo uso el método prototipo .. – vsync

9

Rebecca Murphey hizo una charla sobre literales de objetos en la Conferencia de jQuery de este año. Una de las mejores razones para usarlos es simplemente una buena organización del código.

Aquí es escritura de Rebecca arriba en el objeto literal Patrón: http://rmurphey.com/blog/2009/10/15/using-objects-to-organize-your-code/

+2

Otro gran artículo sobre literales de objetos: http://www.wait-till-i.com/2006/02/16/show-love-to-the-object-literal/ –

2

Ive siempre se utiliza literales de objetos, ya que son una manera clara para organizar código. Por eso no me gusta el prototipo, es demasiado complicado.

Las funciones no contaminan el espacio de nombres como alguien mencionado anteriormente más que los literales de objeto.

Desde aquí se puede escribir como un literal

var obj = {} 
var find = function(elem) { /* find code */ }, 
var doSomething = function() { /* doSomething code */ }, 
var doSomethingElse = function() { /* doSomethingElse code */ } 

que contaminan mediante la creación de una gran cantidad de objetos globales del mismo al igual que las funciones. Del mismo modo que podría hacer:

(function() { 
function find(elem) { /* find code */ }, 
function doSomething() { /* doSomething code */ }, 
function doSomethingElse() { /* doSomethingElse code */ } 
})(); 

que no crearía esos objetos globales (todo es un objeto de JS)

de esa manera usted todavía no se crea un montón de objetos globales.

En mi opinión, los literales de objetos tienen dos ventajas. Uno es utilizado por muchos complementos como jQuery para que las personas sean más familiares y fáciles de leer. Facilitar el paso de datos a un complemento. Es fácil crear métodos públicos y privados ...

Pueden ser lentos, ya que cada vez que crea una instancia del objeto, todos sus métodos están duplicados. Tengo entendido que ese no es el caso con el prototipo ya que tiene una copia de los métodos y los nuevos proyectos simplemente hacen referencia al prototipo.

Podría estar equivocado, por supuesto ...

+1

Los literales de objetos son buenos para el espaciado de nombres y los singletons, cuando crea varias instancias de un objeto con comportamiento compartido, entonces sería mejor usar funciones de constructor. No he encontrado un caso de uso en el que consumir más CPU y memoria simulando formas privadas usando '_myPrivate' en lugar de las partes privadas, pero estaría feliz si alguien puede proporcionarme una. Más sobre el prototipo, la herencia, la mezcla ins aquí: http://stackoverflow.com/a/16063711/1641941 – HMR

Cuestiones relacionadas