2012-04-22 11 views
5

JavaScript semplifica la sovrascrittura di proprietà e funzioni dell'oggetto globale. Mi piacerebbe trovare un modo per verificare se la versione originale di una proprietà globale è stata sostituita.Verificare se una proprietà/funzione globale è stata sovrascritta in JavaScript

consideri qualcuno mettere questo nella loro HTML:

<script type="text/javascript"> 
    window.encodeURIComponent = eval; 
</script> 
<script type="text/javascript" src="myscript.js"></script> 

Se MyScript.js chiama la funzione encodeURIComponent da qualche parte, sarà ora comportarsi in modo imprevedibile. Quindi c'è un modo per controllare all'interno di myscript.js se qualcuno ha sovrascritto quella funzione prima di usarla?

risposta

1

Questo è specifico browser e sicuramente non funziona per i non funzioni, ma:

chiamata metodo toString di una funzione dovrebbe produrre qualcosa di simile:

Chrome: 

"function encodeURIComponent() { [native code] }" 

Firefox: 

"function encodeURIComponent() { 
    [native code] 
}" 

IE 7/8/9: 
" 
function encodeURIComponent() { 
    [native code] 
} 
" 

Si osservi che il nome della funzione corrisponda al nome della struttura e il suo corpo è sostituito da "[native code]". L'idea è di rimuovere tutti gli spazi bianchi da questa stringa e confrontarla con il risultato previsto, "functionxxx(){[nativecode]}".

ho idea se funziona per tutti i browser/funzioni, di che tentativi ed errori:

var pattern = 'function' + propertyName + '(){[nativecode]}'; 
var func = window[propertyName].toString(); 
if(func.replace(/\s+/g, '') !== pattern) { 
    throw new Error("Property window." + propertyName + " has been modified!"); 
} 
6

L'unica cosa che so è un approccio diretto con l'analisi della rappresentazione di stringa della funzione. Normalmente, il codice

window.encodeURIComponent.toString() 

dovrebbe produrre qualcosa come questo:

function encodeURIComponent() { [native code] } 

che può essere facilmente analizzato per informazioni chiave function encodeURIComponent.

Se la funzione è stato sovrascritto da eval, come nel tuo esempio, si otterrà:

function eval() { [native code] } 

In generale, per la verifica window proprietà, è possibile creare un iframe falso e confrontare window.[property].toString() con iframe.contentWindow.[property].toString(). Se il confronto dà false, la proprietà è stata cambiata.

+0

Questo è un modo davvero intelligente e cross-browser per farlo. – sg3s

+0

Grazie Stan. Sapete anche come assicurarsi che la proprietà toString di 'eval' non sia stata sovrascritta con qualcosa come' function() {return "function encodeURIComponent() {[native code]}"; } '? –

+0

invece di analizzare e chiamare 'toString' puoi semplicemente fare questo' window.encodeURIComponent.name' .. QUALUNQUE c'è un metodo più preciese per ottenere questo http://stackoverflow.com/a/10266791/474290 –

0

C'è un modo semplice per farlo in JavaScript :) Ma si deve avere accesso al codice HTML, quindi non è possibile utilizzare questo metodo all'interno di una sceneggiatura ..

funzione è un oggetto .. in modo che possiamo salvare un collegamento a un oggetto e confrontare solo quei collegamenti. Basti pensare a una funzione come un oggetto semplice. Come puoi confrontare gli oggetti?

<script type="text/javascript"> 
    var a = window.encodeURIComponent; // a === window.encodeURIComponent -> true 
</script> 
<script type="text/javascript"> 
    window.encodeURIComponent = eval; // a === window.encodeURIComponent -> false 
</script> 
<script type="text/javascript" src="myscript.js"> 
    if (a !== window.encodeURIComponent) 
    { 
     throw new Error('Someone redefined function'); 
    } 
</script> 
3

Un modo interessante per fare questo all'interno di uno script è di confrontare prototipo di funzione

Per impostazione predefinita - typeof window.encodeURIComponent.prototype === "undefined"

Ma se qualcuno ridefinisce questa funzione

window.encodeURIComponent = function() { eval(); } avremo

typeof window.encodeURIComponent.prototype === "Object"

PS: questo metodo è più affidabile di altri, ma non ti darà il 100% di gurante. JavaScript è tutti gli oggetti e tutte in fase di esecuzione .. basta vivere con questo ..

UPDATE è possibile combinare entrambi i metodi .. la mia e @Stans ..

questo esempio non funzionano perché non ero 't utilizzando eval - eval è anche avere prototipo 'indefinito' per impostazione predefinita .. così si può fare questo

window.encodeURIComponent.name === "encodeURIComponent" 
//to make shure that user won't use EVAL 
&& typeof window.encodeURIComponent.prototype === "undefined" 
//to make shure that user won't use self defined function 
+0

Ai_boy, non riesco a riprodurlo. 'typeof window.encodeURIComponent.prototype' è' "undefined" 'in entrambi i casi. –

+0

vedi un aggiornamento .. –

0

ne dici di questo?

function isNativeWindowProperty(propertyName) { 
    var result = false; 
    var iframe = document.createElement('iframe'); 
    iframe.src = 'javascript:;'; 
    document.getElementsByTagName('body')[0].appendChild(iframe); 
    if (window[propertyName].toString() === iframe.contentWindow[propertyName].toString()) { 
     // check window[propertyName].toString override 
     if (window[propertyName].toString.toString() === iframe.contentWindow[propertyName].toString.toString()) { 
      result = true; 
     } 
    } 
    iframe.parentNode.removeChild(iframe); 
    return result; 
}; 

console.log(isNativeWindowProperty('alert')); // true 

window.alert = function() {}; 
console.log(isNativeWindowProperty('alert')); // false 

window.alert.toString = function() { 
    return 'function alert() { [native code] }'; 
}; 
console.log(isNativeWindowProperty('alert')); // false 
+0

Forse potresti aggiungere del testo per spiegare come il tuo codice risponde al queston? – Kmeixner

Problemi correlati