2012-04-22 9 views
5

JavaScript ułatwia nadpisanie właściwości i funkcji obiektu globalnego. Chciałbym znaleźć sposób na sprawdzenie, czy oryginalna wersja właściwości globalnej została zastąpiona.Sprawdź, czy właściwość/funkcja globalna została nadpisana w JavaScript

Rozważmy ktoś oddanie tego w ich HTML:

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

Jeśli myscript.js wywołuje funkcję encodeURIComponent gdzieś będzie teraz zachowywać się nieprzewidywalnie. Czy istnieje sposób, aby sprawdzić wewnątrz myscript.js, czy ktoś nadpisał tę funkcję, zanim ją wykorzystam?

Odpowiedz

1

Jest to przeglądarka specyficzna i na pewno nie będzie działać tylko dla funkcji, ale:

Wywołanie funkcji za toString metoda powinna produkować coś takiego:

Chrome: 

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

Firefox: 

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

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

Zauważ, że nazwą funkcji mecze nazwę m.in. , a jego treść zostaje zastąpiona przez "[native code]". Chodzi o to, aby usunąć wszystkie spacje z tego łańcucha i porównać je z oczekiwanym wynikiem, "functionxxx(){[nativecode]}".

nie mam pojęcia, czy to działa na wszystkich przeglądarkach/funkcji, to metodą prób i błędów:

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

Jedyne co wiem, to proste podejście z analizy reprezentacji ciąg funkcji. Normalnie kod

window.encodeURIComponent.toString() 

powinna produkować coś takiego:

function encodeURIComponent() { [native code] } 

które mogą być łatwo analizowane dla kluczowej informacji function encodeURIComponent.

Jeśli funkcja została zastąpione przez eval, jak w przykładzie, dostaniesz:

function eval() { [native code] } 

w ogóle, do sprawdzania window właściwości, można stworzyć fałszywy iframe i porównanie window.[property].toString() z iframe.contentWindow.[property].toString(). Jeśli porównanie daje false, właściwość została zmieniona.

+0

To naprawdę sprytny sposób na zrobienie tego w różnych przeglądarkach. – sg3s

+0

Dzięki Stan. Czy wiesz również, jak zapewnić, że własność toString 'eval' nie została nadpisana przez coś takiego jak funkcja' function() {return "encodeURIComponent() {[native code]}"; } '? –

+0

zamiast parsowania i wywoływania 'toString' możesz po prostu zrobić to' window.encodeURIComponent.name' .. ANYWAY istnieje bardziej precyzyjna metoda osiągnięcia tego http://stackoverflow.com/a/10266791/474290 –

0

istnieje łatwy sposób to zrobić w JavaScript :) Ale trzeba mieć dostęp do HTML, więc nie można użyć tej metody wewnątrz jednego skryptu ..

funkcja jest obiekt .. więc możemy zapisać link do obiektu i po prostu porównać te linki. Wystarczy pomyśleć o funkcji podobnej do prostego obiektu. Jak porównać obiekty?

<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

Jeden ciekawy sposób to zrobić wewnątrz jednego skryptu jest porównanie prototyp funkcji

Domyślnie - typeof window.encodeURIComponent.prototype === "undefined"

Ale jeśli ktoś nowo tę funkcję przez

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

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

PS: ta metoda jest bardziej niezawodna niż inne, ale nie da ci 100% gurante. JavaScript to wszystkie obiekty, a wszystko to w czasie wykonywania .. po prostu z tym żyć ..

UPDATE można połączyć obie metody .. moja i @Stans ..

ten przykład nie działa, bo nie był „t korzystając eval - eval ma także prototyp«nieokreśloną»domyślnie .. więc można to zrobić

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, nie mogę tego odtworzyć. 'typeof window.encodeURIComponent.prototype' to" "undefined" 'w obu przypadkach. –

+0

zobacz aktualizację. –

0

Jak ten temat?

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

Może mógłbyś dodać tekst wyjaśniający, w jaki sposób twój kod odpowiada na zadanie? – Kmeixner

Powiązane problemy