2010-07-10 21 views
5

He estado tratando de ver si puedo construir mis objetos de JavaScript de la manera más intuitiva posible, asegurándome de que sea lo más 'correcto' posible. He estado corriendo un montón de escenarios diferentes a través de JSLint.com de Crockford y no he tenido mucha suerte. Parece que soluciono un error, luego aparece otro debido al cambio. A continuación es tan bueno como puedo obtener. Alguien tiene otra opinión sobre esto?¿Cuál es la mejor manera de crear un objeto JavaScript para que funcione Y pase JSLint?

Esta es una forma típica estructuro un objeto:

function gizmo(id) { 

    /* private variables */ 

    var myId = id; 

    /* private methods */ 

    var init = function() { 
    if (myId < 1) { 
     setId(1); 
    } 
    }; 

    var setId = function (newId) { 
    myId = newId; 
    }; 

    // run 'constructor' 
    init(); 

    /* public methods */ 

    return { 
    getId: function() { 
     return myId; 
    }, 
    setId: function (newId) { 
     setId(newId); 
    }, 
    incrementId: function (inc) { 
     setId(myId + inc); 
    } 
    }; 
} 

// creating an instance of gizmo 

var myGizmo = gizmo(-2); 
console.log(myGizmo.getId()); // outputs 1 

myGizmo.setId(5); 
console.log(myGizmo.getId()); // outputs 5 

myGizmo.incrementId(2); 
console.log(myGizmo.getId()); /// outputs 7 

Esto parece funcionar bien. Sin embargo, cuando ejecuto esto a través de JSLint, me da un error que indica que mis dos funciones privadas son 'Implied Globals'.

Lo mejor que puedo llegar a es declarar mis funciones en la parte superior con las variables de este tipo:

function gizmo(id) { 

    /* private variables */ 

    var myId = id, 
     init, 
     setId; 

    /* private methods */ 

    init = function() { 
    if (myId < 1) { 
     setId(1); 
    } 
    }; 

    setId = function (newId) { 
    myId = newId; 
    }; 

    // run 'constructor' 
    init(); 

    /* public methods */ 

    return { 
    getId: function() { 
     return myId; 
    }, 
    setId: function (newId) { 
     setId(newId); 
    }, 
    incrementId: function (inc) { 
     setId(myId + inc); 
    } 
    }; 
} 
+2

Esto no es tanto una respuesta como un consejo. No te preocupes demasiado por jsLint. A menudo me parece demasiado estricto. Enfoque en la programación en su lugar. Dicho eso, dejaré que otros discutan las mejores prácticas. – TNi

+0

De acuerdo. No lo estreso demasiado. Solo tengo mi manera de estructurar mi código en función de lo que he aprendido aquí y allá en los interwebs. He estado jugando con JSLint en los últimos días y estaba interesado en obtener la opinión de otras personas sobre todo. –

+0

el problema es init y el orden de sus funciones. Mueve init justo antes de devolver el objeto que pasará. Además, no creo que necesites la función init. Tal vez como un fn autoejecutable y anónimo solo para separar cosas. – galambalazs

Respuesta

1

Estoy bastante seguro de que es un error en JSLint. Todavía no ha visto setId, por lo que asume que es global. Pero en realidad, no hace ninguna diferencia, porque todos los var s están izados, por ECMAScript 5 10.5. Esto significa que su primer ejemplo y el segundo son los mismos semánticamente. Una declaración de variable local en cualquier lugar en la función se procesa inmediatamente, y el enlace se establece inicialmente para tener el valor undefined. Pero cuando se ejecuta realmente la función (por ejemplo, init), el valor cerrado ya no es undefined.

ver que setId es inicialmente definido, pero nunca se refiere a un mundial, hacer esta prueba:

function setId() 
{ 
    alert("Global setId"); 
} 
function f() 
{ 
    var init = function() 
    { 
    setId(); 
    } 
    alert(typeof(setId)); 
    init(); 
    var setId = function() 
    { 

    } 
} 

Se alerta indefinido, luego tirar un error de TypeError.

+0

+1, no sabía acerca de izar. Siempre asumí que tenías que declarar las cosas en orden. – gradbot

+0

Debe declararlos en orden si desea que funcionen en todos los navegadores. – lawnsea

+0

@lawnsea, ¿qué navegador se comporta de forma diferente y cómo? –

0

No sé sobre JSLint, pero después de leer "javascript las partes buenas", Yo siempre declaro los objetos como literales.

por ejemplo:

Mogwai={ 
    has_crazy_thoughts:True, 
    reacts_to_water:True, 
    name: 'Gizmo', 
    eat:function(food){ 
    // code 
    }, 
    become_gremlin:function(){ 
    // code 
    }, 
    cause_havoc:function(){ 
    // code 
    } 
} 

Usted no está realmente declarar los objetos anteriormente. Solo una función Las funciones internas realmente no existen en Javascript, no es como Java en absoluto.

EDIT: Recomiendo encarecidamente el libro mencionado anteriormente (sin afiliación): http://oreilly.com/catalog/9780596517748 ... está escrito por Douglas Crockford, quien nos trajo JSlint.

+1

Soy dueño del libro. Y sí, está bien. Mi ejemplo anterior crea variables privadas y funciona usando cierres, que es algo que Crockford repasa también en ese libro. Con su ejemplo, simplemente usando literales de objeto, no tengo forma de crear variables privadas o funciones. –

+0

En realidad, estás declarando un objeto. Está declarando un objeto, así como tres funciones, dos booleanos y una cadena, todo relleno en las propiedades del objeto. – icktoofay

+0

Además, 'True' y' False' son minúsculas en JavaScript. – icktoofay

3

JSLint espera que setId se defina antes de que se haga referencia en init.

Pasa JSLint.

function gizmo(id) { 

    /* private variables */ 

    var myId = id; 

    /* private methods */ 

    var setId = function (newId) { 
    myId = newId; 
    }; 

    var init = function() { 
    if (myId < 1) { 
     setId(1); 
    } 
    }; 

    // run 'constructor' 
    init(); 

    /* public methods */ 

    return { 
    getId: function() { 
     return myId; 
    }, 
    setId: function (newId) { 
     setId(newId); 
    }, 
    incrementId: function (inc) { 
     setId(myId + inc); 
    } 
    }; 
} 
+0

no hace ninguna diferencia si defino mi función usando la función setId() obtengo el mismo error global implícito en JSLint. –

+0

Acabo de ejecutar esto a través de JSLint y se aprobó. Pruébalo en su sitio web. http://www.jslint.com/ – gradbot

+1

'setId' nunca se refiere a un global. Debido a la elevación, siempre se refiere a la variable local. Es cierto que el valor de esta variable local no está definido inicialmente, pero eso es irrelevante porque se define cuando se llama a 'init'. –

0

Ha sido un largo tiempo (varios años), ya que he programado JavaScript en serio, así que mi memoria en los detalles de las mejores prácticas se fuese. Lo que hice se remonta y saqué algunos recursos que pueden ayudarlo a tomar una decisión informada.

En primer lugar, la forma en que está creando sus objetos parece muy reminiscente de Module Pattern. Por lo que recuerdo, el artículo al que me he vinculado es una buena lectura sobre eso. En segundo lugar, tal vez prefiera una forma diferente de instantiate your objects. Ese artículo te da una perspectiva ligeramente diferente.

+0

Cool. Leyendo la publicación de Resig sobre eso ahora. Gracias. –

Cuestiones relacionadas