2010-03-04 12 views
20

Sto lavorando su un plug-in per jQuery e sto ottenendo questo errore JSLint:Quali effetti collaterali ha la parola "nuovo" in JavaScript?

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

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

non ho avuto molta fortuna informazioni trovare su questo errore JSLint o su eventuali effetti collaterali che potrebbe new avere.

Ho provato Googling per "Non utilizzare" nuovo "per gli effetti collaterali". e ha ottenuto 0 risultati. Binging mi dà 2 risultati ma entrambi fanno semplicemente riferimento alla fonte JSLint. Speriamo che questa domanda cambierà questo. :-)

Update # 1: Qui c'è di più fonte per il contesto:

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

Aggiornamento # 2: ho usato il Starter jQuery plug-in generator come modello per il mio plug-in, che ha quel codice in esso.

+0

Ho twitterato all'autore dello Starter :-) – Pointy

+1

Guardando il codice "Starter", ho aggiornato la mia risposta qui sotto - ci sono davvero degli effetti collaterali e vengono utilizzati da quel codice generato. – Pointy

+0

@Pointy Non ho mai ricevuto il tuo tweet, dove l'hai mandato? @dougneiner? Mi dispiace per quello! –

risposta

7

Travis, sono lo sviluppatore del sito Starter.

@Pointy ha colpito il chiodo sulla testa. La ragione per cui il codice Starter è scritto in questo modo è perché abbiamo bisogno di un nuovo oggetto, semplicemente non abbiamo bisogno di memorizzare un riferimento ad esso in quel punto.

semplicemente cambiando il comando dal

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

a

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

placherà JSLint come avete trovato.

La configurazione del plug-in di Starter segue il pattern dell'interfaccia utente jQuery di memorizzazione di un riferimento all'oggetto nel set data per l'elemento. Quindi questo è ciò che sta accadendo:

  1. nuovo oggetto viene creato (tramite nuovo)
  2. L'istanza è collegato all'elemento DOM utilizzando jQuery data: $(el).data('FasterTrim', this)

Non v'è alcuna utilità per l'oggetto che viene restituito e quindi nessuna dichiarazione var effettuata. Cercherò di cambiare la dichiarazione e di pulire l'output per passare JSLint fuori dalla scatola.

Un po 'più di fondo:

Il vantaggio per memorizzare l'oggetto utilizzando data è che siamo in grado di accedere all'oggetto in seguito in qualsiasi momento chiamando: $("#your_selector").data('FasterTrim'). Tuttavia, se il tuo plugin non ha bisogno di accedere a mid stream in questo modo (Significato, viene impostato in una singola chiamata e non offre alcuna interazione futura) quindi non è necessario memorizzare un riferimento.

Fatemi sapere se avete bisogno di maggiori informazioni.

+0

Cool, grazie Doug. L'impostazione di una variabile mi darebbe solo un altro errore di sfilacciamento sulla falsariga di "Variabile inutilizzata: fT", quindi manterrò semplicemente il codice di avviamento. – travis

+1

Se ti infastidisce davvero (e potrei cadere nella categoria di ossessionato da JSLint quando lo uso) potresti spostare la chiamata 'data' dopo il costruttore in questo modo:' var fT = new jQuery.fasterTrim (this, options) ; $ (this) .data ('FasterTrim', fT); 'E questo risolverebbe gli errori che io penso. –

+0

Tranne che il JSLint di oggi ti darà un errore 'Inutilizzato 'fT''. La lezione di JSLint? Non essere un [JavaScript javascript] (http://www.reddit.com/r/programming/comments/sag8p/crockford_on_bootstraps_semicolon_omission/c4ci37g). ; ^) – ruffin

6

Si lamenta perché stai chiamando "nuovo" ma poi buttando via l'oggetto restituito, scommetto. Perché quel codice utilizza "nuovo"? In altre parole, perché non è solo

jQuery.fasterTrim(this, options); 

modificare OK, bene che funzione "Starter" genera il codice in questo modo perché in realtà non vuole un nuovo oggetto creato, e sì, è davvero di prendere vantaggio degli effetti collaterali. Il codice costruttore che "Starter" genera rappresenta un riferimento al nuovo oggetto sull'elemento interessato, utilizzando la funzione "dati" di jQuery.

+0

Ho aggiornato la domanda per mostrare la sorgente circostante, originata dal codice di avviamento. – travis

+0

Il problema rilevato da js lint è la creazione di un nuovo oggetto e il suo lancio.Fondamentalmente, jslint presuppone che una nuova chiamata il cui valore di ritorno non sia memorizzato debba causare un effetto collaterale (perché altrimenti lo istanziate), ei costruttori con effetti collaterali sono in genere di pessima progettazione. Js lint ti sta dicendo che fastTrim usa un cattivo design. Basta usare $ .fasterTrim ("Hello"); –

+0

@Juan bene sembra che lo strumento "Starter" generi quel codice, quindi il richiedente della domanda è fondamentalmente una vittima di quella roba. Ho usato quella pagina io stesso proprio ora, e abbastanza sicuro che sembra essere lo schema che ti dà. Non so perché. – Pointy

5

Si sta utilizzando new per eseguire alcune azioni invece di creare un oggetto e restituirlo. JSLint considera questo un uso non valido di new.

Si dovrebbe usare sia in questo modo:

var x = new SomeConstructor(); 

O eseguire alcune azioni in questo modo:

SomeMethod(); 

Ma mai utilizzare nuovo per eseguire un'azione simile a questo:

new SomeCosntructor(args); 

Questo è considerato utilizzando new per gli effetti collaterali perché non lo si sta utilizzando per creare te un oggetto.

+1

beh, sta creando un oggetto, ma lo sta buttando via :-) – Pointy

+0

Ho aggiornato la domanda per mostrare la sorgente circostante, che ha avuto origine dal codice di avviamento. – travis

+0

Non riesco ancora a capire. Come posso creare qualcosa come Prototype PeriodicalExecuter? L'API consigliata fallisce questo controllo jslint. http://www.prototypejs.org/api/periodicalExecuter – ScottJ

2

Fondamentalmente JavaScript tende ad essere un animale lento, quindi creare un nuovo oggetto solo per chiamare una funzione è abbastanza inefficiente. La funzione è statica comunque.

$.fasterTrim(this, options); 
15

JsLint itself ti dà la ragione:

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

Da jQuery fasterTrim source code:

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

Per rispondere alla domanda, "Non usare di nuovo per gli effetti collaterali" 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, grazie per aver incollato la mia fonte per me :-) – travis

Problemi correlati