2010-03-04 15 views
20

Estoy trabajando en un plug-in para jQuery y yo estoy poniendo este JSLint de error:¿Qué efectos secundarios tiene la palabra clave 'nuevo' en JavaScript?

Problem at line 80 character 45: Do not use 'new' for side effects. 

(new jQuery.fasterTrim(this, options)); 

no he tenido mucha suerte de encontrar información sobre este error JSLint o de cualquier efecto secundario que new poder tener.

He intentado Googling para "No utilizar 'nuevo' para los efectos secundarios." y obtuve 0 resultados. Binging me da 2 resultados, pero ambos solo hacen referencia a la fuente JSLint. Espero que esta pregunta cambie eso. :-)

Actualización # 1: Aquí hay más fuente para el contexto:

jQuery.fn.fasterTrim = function(options) { 
    return this.each(function() { 
     (new jQuery.fasterTrim(this, options)); 
    }); 
    }; 

Actualización # 2: he utilizado la Starter jQuery plug-in generator como una plantilla para mi plug-in, el cual tiene ese código en ella

+0

He twittered en el autor de inicio :-) – Pointy

+1

Miré el código "Starter", actualicé mi respuesta a continuación: realmente hay efectos secundarios y están siendo utilizados por ese código generado. – Pointy

+0

@Pointy Nunca recibí tu tweet, ¿a dónde lo enviaste? @dougneiner? ¡Lo siento por eso! –

Respuesta

7

Travis, soy el desarrollador detrás del sitio Starter.

@Pointy golpeó el clavo en la cabeza. La razón por la que el código de inicio está escrito de esa manera es porque necesitamos un nuevo objeto, simplemente no necesitamos almacenar una referencia en ese punto.

Simplemente cambiando el comando desde

(new jQuery.fasterTrim(this, options)); 

a

var fT = new jQuery.fasterTrim(this, options); 

apaciguar JSLint como has encontrado.

La configuración del complemento de inicio sigue el patrón jQuery UI de almacenar una referencia al objeto en el conjunto data para el elemento. Así que esto es lo que está sucediendo:

  1. nuevo objeto se crea (a través de nuevo)
  2. La instancia está unido al elemento DOM utilizando jQuery data: $(el).data('FasterTrim', this)

No hay un uso para el objeto que se devuelve y, por lo tanto, no se ha realizado ninguna declaración var. Buscaré cambiar la declaración y limpiar la salida para pasar JSLint de fábrica.

Un poco más antecedentes:

El beneficio para almacenar el objeto utilizando data es que podemos acceder al objeto más adelante en cualquier momento llamando a: $("#your_selector").data('FasterTrim'). Sin embargo, si no necesita acceder a su complemento a mitad de la transmisión de esa manera (lo que significa que se configura en una sola llamada y no ofrece interacción futura), no es necesario almacenar una referencia.

Avíseme si necesita más información.

+0

Cool, gracias Doug. Establecer una var me daría otro error de pelusa en la línea de 'Variable no utilizada: fT', así que mantendré el código de inicio tal como está. – travis

+1

Si realmente te molesta (y podría caer en la categoría de obsesionado con JSLint cuando lo uso) podrías mover la llamada 'data' después del constructor así:' var fT = new jQuery.fasterTrim (this, options) ; $ (this) .data ('FasterTrim', fT); 'Y eso resolvería los errores que yo piense. –

+0

Excepto que el JSLint de hoy le dará un error 'No utilizado 'fT''. La lección de JSLint? No seas [JavaScript hipster] (http://www.reddit.com/r/programming/comments/sag8p/crockford_on_bootstraps_semicolon_omission/c4ci37g). ; ^) – ruffin

6

Se queja porque está llamando "nuevo" pero luego tirando el objeto devuelto, apuesto. ¿Por qué ese código usa "nuevo"? En otras palabras, ¿por qué no se trata sólo de

jQuery.fasterTrim(this, options); 

edición bien, así que la herramienta "arranque" genera el código de esa manera porque realmente quiere un nuevo objeto creado, y sí lo que realmente es tomar ventaja de los efectos secundarios. El código de constructor que "Starter" genera esconde una referencia al nuevo objeto en el elemento afectado, utilizando el recurso jQuery "data".

+0

Actualicé la pregunta para mostrar la fuente circundante, que se originó a partir del código de inicio. – travis

+0

El problema que js pelusa detectó es crear un nuevo objeto y tirarlo.Básicamente, jslint asume que una nueva llamada cuyo valor devuelto no se almacena debe causar un efecto secundario (¿por qué otra razón lo crearía), y los constructores con efectos secundarios generalmente son malos diseños? Js lint te está diciendo que fastTrim usa mal diseño. Simplemente use $ .fasterTrim ("Hola"); –

+0

@Juan bien, parece que la herramienta "Iniciador" genera ese código, por lo que el que pregunta es básicamente víctima de eso. He usado esa página yo mismo ahora, y por supuesto que parece ser el patrón que te da. No sé por qué. – Pointy

5

Está utilizando new para realizar alguna acción en lugar de crear un objeto y devolverlo. JSLint considera esto un uso no válido de new.

Debe o bien utilizar de esta manera:

var x = new SomeConstructor(); 

o realizar alguna acción como esta:

SomeMethod(); 

Pero nunca utilice nueva para llevar a cabo una acción como esta:

new SomeCosntructor(args); 

Hacer esto se considera usar new para efectos secundarios porque no lo está usando para crear te un objeto.

+1

bueno, él está creando un objeto, pero lo está tirando :-) – Pointy

+0

He actualizado la pregunta para mostrar la fuente circundante, que se originó a partir del código de inicio. – travis

+0

Todavía no entiendo. ¿Cómo puedo crear algo así como un Prototype PeriodicalExecuter? La API recomendada falla esta comprobación jslint. http://www.prototypejs.org/api/periodicalExecuter – ScottJ

2

Básicamente, JavaScript tiende a ser una bestia lenta, por lo que crear un objeto nuevo solo para llamar a una función es bastante ineficiente. La función es estática de todos modos.

$.fasterTrim(this, options); 
15

JsLint itself le da la razón:

Constructors are functions that are designed to be used with the new prefix. The new prefix creates a new object based on the function's prototype, and binds that object to the function's implied this parameter. If you neglect to use the new prefix, no new object will be made and this will be bound to the global object. This is a serious mistake.

JSLint enforces the convention that constructor functions be given names with initial uppercase. JSLint does not expect to see a function invocation with an initial uppercase name unless it has the new prefix. JSLint does not expect to see the new prefix used with functions whose names do not start with initial uppercase. This can be controlled with the newcap option.

JSLint does not expect to see the wrapper forms new Number, new String, new Boolean.

JSLint does not expect to see new Object (use {} instead).

JSLint does not expect to see new Array (use [] instead).

0

De jQuery fasterTrim source code:

* Usage: 
* 
* $(element).fasterTrim(options); // returns jQuery object 
* $.fasterTrim.trim(" string ", options); // returns trimmed string 

Para responder a la pregunta: "No utilice nueva para los efectos secundarios" significa:

Do not use new for what the constructor will do to its parameters but to create an object, side effects in constructors are baaaad!

+2

ha, gracias por pegar mi propia fuente para mí :-) – travis

Cuestiones relacionadas