Perché questo è illegale in modalità rigorosa?
-
29-09-2019 - |
Domanda
Sì, sì, lo so, la modalità rigorosa non è ancora in giro, ma in realtà, sto progettando per il futuro ...
Quindi, perché è questa:
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
... non ammessi in modalità Strict ES5?
o sto interpretando male? JSLint:
Problem at line 516 character 18: Strict violation.
Potrebbe essere un po 'più dettagliato, mi chiedo ...?
EDIT:
Per evitare confusione, qui c'è di più del codice originale:
function displayLegend() {
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
}
Soluzione
Alcuni tentativi ed errori di questo codice in JSLint
"use strict";
var that="dd";
function $(x){return x;}
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
$(this);
mi mostra ciò che è sbagliato: si sta utilizzando this
come parametro. Cambiare entrambe this
es a that
s non fa scattare l'errore.
la specifica dice:
Se questo viene valutata all'interno rigido codice modalità, allora il questo il valore non è costretto a un oggetto. A questo valore Null o indefinito non viene convertito all'oggetto globale e valori primitivi non vengono convertiti in oggetti wrapper. Il questo valore passato tramite una chiamata di funzione (tra cui le chiamate effettuate utilizzando Function.prototype.apply e Function.prototype.call ) fare non costringere il passato questo il valore di un oggetto ( 10.4.3 , 11.1.1 , 15.3.4.3 , 15.3.4.4 ). [corsivo mio]
Come John Resig scrive ,
Infine, una lunga (e molto fastidioso) bug è stato risolto: Casi dove null o undefined è costretto a diventare l'oggetto globale. Modalità rigorosa ora impedisce che ciò accadendo e genera un'eccezione invece.
(function(){ ... }).call( null ); // Exception
Come hai mostrato, utilizzando la linea di codice all'interno di una dichiarazione di funzione genera un errore in JSLint, mentre l'uso all'interno di un'espressione di funzione non è così. Sembra JSLint analizza erroneamente la dichiarazione di funzione, vede this
, che è ancora indefinito, in quel momento, e genera un'eccezione.
A questo punto, penso di avere per citare Juriy Zaytsev ( 'kangax') :
È veramente importante?
E 'bene capire che modalità rigorosa non è un requisito , ma è solo un'opzione. E 'lì per fornire norme più severe per coloro che bisogno, e sono disposti a far fronte alle (E godere) conseguenze.
Aggiornamento: Finalmente ho trovato una spiegazione. Se andate a leggere questa discussione , in particolare dal messaggio # 1512 in poi, si legge che
Il punto di ES5 / rigorosa è di vietare che perde dell'oggetto globale, qualcosa che fa ES3 promiscuamente. ES5 / rigoroso fa parte del suo lavoro in modo dinamico, e alcuni dei suoi lavori staticamente. JSLint fa tutta la sua lavorare in modo statico, quindi deve essere ancora più restrittivi al fine di miglior aiuto si ottiene il giusto programma. [Douglas Crockford a # 1553]
Devo ammettere che ha un valido punto qui: se il tuo obiettivo è quello di evitare l'inquinamento namespace globale, non si dovrebbe usare dichiarazioni di funzioni, ma le espressioni di funzione all'interno di uno spazio dei nomi privato, in ogni caso. Ma sono d'accordo con gli altri nella discussione detto che il messaggio di errore dovrebbe essere più esplicito (e probabilmente gettare un avviso sul incontrando una dichiarazione di funzione).
Altri suggerimenti
A seguito di ciò che ha detto David Dorward, ho trovato qualcosa che passa il test di JSLint. Questo è decisamente strano per spiegare perché sta facendo questo.
Prima: (vedi domanda)
Dopo:
var displayLegend = function () {
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
};
EDIT:
Ho chiesto Douglas Crockford:
JSLint consente solo questo in modalità rigorosa in funzioni che sono ovviamente destinati ad essere chiamato come metodi. Così scrittura
object.property = function () { ... this ... };
Ciò conferma quello che dice nelle specifiche, tranne che è molto più chiaro!