2013-03-13 6 views
6

Dire che ho il seguente codice:Ridefinire la costruzione Array in javascript

var secrets; 
Array = function() { 
    secrets = this; 
}; 

L'autore del campione sopra dice che il codice sta ridefinendo la costruzione Array. Innanzitutto, non sono sicuro di cosa si riferisca a this. Qualcuno può consigliare?

Secondo: il seguente codice è equivalente?

var secrets; 
function Array() { 
    secrets = this; 
} 

Tra l'altro il codice di cui sopra è presa dal seguente articolo su una vulnerabilità JSON: see here

+3

È stanno facendo due domande qui. Come funziona 'questo' è spiegato [nella documentazione MDN] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this) (in breve: il valore dipende da come la funzione è chiamato) e se 'Array = function() ...' o 'function Array() ...' sono la stessa risposta [in questa domanda] (http://stackoverflow.com/q/336859/218196). –

+0

grazie Felix. Per quanto riguarda "questo", ho letto la documentazione ma non sono riuscito a capire che cosa "questo" si riferisce a ** nel contesto di cui sopra ** ... Puoi aiutarci, per favore? Per quanto riguarda la seconda parte della mia domanda, ho letto il post che hai fornito e ora capisco meglio. – balteo

+1

Se chiamate 'Array' con' new', allora si riferirà ad un oggetto vuoto che eredita da 'Array.prototype'. Se viene chiamato senza 'new', si riferirà a' window'. Se viene chiamato tramite '.call' o' .apply', si riferirà all'elemento che viene passato come primo argomento. Per sapere come è chiamato, devi dare un'occhiata a 'JSON.parse'. –

risposta

5

In entrambi gli esempi si sta definendo la variabile Array come function che assegna this a secrets. Succede che esiste già un oggetto globale chiamato Array che altri JS nella pagina potrebbero o non potrebbero usare come Constructor per creare array. Se si accede alla console e si assegna nuovamente l'array a qualcos'altro, è possibile iniziare a ricevere errori dal codice che dipende esplicitamente da Array. Tuttavia, gli array realizzati letteralmente con [] continuano a funzionare correttamente e in effetti il ​​loro __proto__ punta ancora a ciò che era Array.prototype. Quindi:

var arr1 = new Array('a','b','c'); 
// arr[0] -> 'a' 

var arr2 = ['d','e','f']; 
// arr[0] -> 'd' 

var secrets; 
Array = function() { secrets = this; }; 

var arr3 = new Array('g','h','i'); // nothing wrong here, because Array is a function 
// arr3[0] -> undefined 
// Array is just a function, you can't make arrays with new Array anymore 
// and arr3 is just a function 


var arr4 = ['j','k','l']; 
// arr4[0] -> 'j' 
// making array literals still works 

come per this, nulla di strano, segue ancora le regole del this. il fatto che stai assegnando una funzione a Array non modifica il comportamento di this. così this punti all'oggetto globale che nel browser è window a meno che non si crea un'istanza con new o utilizzare call o apply

la differenza tra i due campioni è la differenza tra un'espressione di funzione e di dichiarazione di funzione, vedere: What is the difference between a function expression vs declaration in Javascript?

1

Sì, entrambi i frammenti sono equivalenti. Entrambi ridefiniscono il costruttore di array, nel tentativo di intercettare tutti i dati dell'array utilizzati dal sito Web in cui è stato iniettato, come spiegato nell'articolo collegato. Il valore di this dovrebbe essere l'array appena costruito.

Questo sembra essere stato consentito da ECMAScript 3, ma non consentito da ECMAScript 5, ora disponibile su tutti i browser moderni. Quindi l'exploit descritto nell'articolo non dovrebbe più funzionare.

+0

L'exploit non funziona più perché JSON.parse o literal conformi alla norma non chiamano 'Array'. Vedere la mia risposta a http://stackoverflow.com/q/13040367/1048572 – Bergi

+0

Sì, questo è ciò che intendevo. Precedentemente qualcosa come 'eval ('[1,2,3]')' chiamava il costruttore ridefinito. – bfavaretto

+0

ma funzionerebbe ancora su array creati con 'new Array()' – C5H8NNaO4