2012-04-22 42 views
5

JavaScript giúp bạn dễ dàng ghi đè các thuộc tính và chức năng của đối tượng chung. Tôi muốn tìm cách kiểm tra xem phiên bản gốc của thuộc tính toàn cầu đã được thay thế chưa.Kiểm tra xem thuộc tính/chức năng toàn cầu đã được ghi đè trong JavaScript

Hãy xem xét một ai đó đặt này trong HTML của họ:

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

Nếu myscript.js gọi hàm encodeURIComponent nơi nào đó, bây giờ nó sẽ cư xử thất thường. Vì vậy, có một cách tôi có thể kiểm tra bên trong myscript.js nếu ai đó đã ghi đè chức năng đó trước khi tôi sử dụng nó?

Trả lời

1

Đây là trình duyệt cụ thể và chắc chắn sẽ không làm việc cho phi chức năng, nhưng:

gọi method của một chức năng toString nên sản xuất cái gì đó như:

Chrome: 

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

Firefox: 

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

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

Quan sát rằng tên của chức năng phù hợp với tên của bất động sản và phần thân của nó được thay thế bằng "[native code]". Ý tưởng là xóa tất cả khoảng trắng khỏi chuỗi này và so sánh nó với kết quả mong đợi, "functionxxx(){[nativecode]}".

Tôi không có ý tưởng nếu nó hoạt động cho tất cả các trình duyệt/chức năng, mà của thử và sai:

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

Điều duy nhất tôi biết là một cách tiếp cận đơn giản với phân tích của đại diện chuỗi của hàm. Thông thường, mã

window.encodeURIComponent.toString() 

nên sản xuất cái gì đó như thế này:

function encodeURIComponent() { [native code] } 

có thể dễ dàng phân tích để biết chính function encodeURIComponent.

Nếu hàm được ghi đè bởi eval, như trong ví dụ của bạn, bạn sẽ nhận được:

function eval() { [native code] } 

Nói chung, để kiểm tra window tính, bạn có thể tạo một iframe giả và so sánh window.[property].toString() với iframe.contentWindow.[property].toString(). Nếu so sánh cung cấp false, thuộc tính đã được thay đổi.

+0

Đây là cách thực sự thông minh và đa trình duyệt. – sg3s

+0

Cảm ơn Stan. Bạn cũng biết làm thế nào để đảm bảo rằng thuộc tính toString của 'eval' không được ghi đè bằng một cái gì đó như hàm' function() {return "encodeURIComponent() {[native code]}"; } '? –

+0

thay vì phân tích cú pháp và gọi 'toString', bạn chỉ cần thực hiện điều này' window.encodeURIComponent.name' .. BẤT CỨ có phương thức preciese hơn để đạt được http://stackoverflow.com/a/10266791/474290 –

0

Có một cách dễ dàng để làm điều đó trong JavaScript :) Nhưng bạn phải có quyền truy cập vào mã HTML, vì vậy bạn không thể sử dụng phương pháp này bên trong một kịch bản ..

chức năng là một OBJECT .. vì vậy chúng tôi có thể lưu liên kết đến một đối tượng và chỉ cần so sánh các liên kết đó. Chỉ cần nghĩ về một hàm giống như một đối tượng đơn giản. Làm thế nào bạn có thể so sánh các đối tượng?

<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

Một cách thú vị để làm điều này trong một kịch bản là so sánh chức năng nguyên mẫu

Theo mặc định - typeof window.encodeURIComponent.prototype === "undefined"

Nhưng nếu ai đó định nghĩa lại chức năng này bằng cách

window.encodeURIComponent = function() { eval(); } chúng tôi sẽ nhận được

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

PS: phương pháp này đáng tin cậy hơn những phương pháp khác, nhưng nó sẽ không cung cấp cho bạn 100% gurante. JavaScript là tất cả các đối tượng và tất cả trong thời gian chạy .. chỉ sống với điều này ..

CẬP NHẬT bạn có thể kết hợp cả hai phương pháp .. mỏ và @Stans ..

ví dụ này không làm việc vì tôi wasn 't sử dụng eval - eval cũng là có nguyên mẫu 'không xác định' theo mặc định .. vì vậy bạn có thể làm điều này

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, tôi dường như không thể tái tạo điều đó. 'typeof window.encodeURIComponent.prototype' là' "undefined" 'trong cả hai trường hợp. –

+0

xem bản cập nhật .. –

0

làm thế nào về điều này?

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

Có thể bạn có thể thêm một số văn bản để giải thích cách mã của bạn trả lời queston? – Kmeixner

Các vấn đề liên quan