2012-07-17 49 views
6

這個問題是關係到What are the best practices to follow when declaring an array in Javascript?你可以添加一個函數到被劫持的JavaScript數組嗎?


比方說,一個客戶端,我們姑且稱之爲"D. B. Cooper",有下面的代碼必須在其他任何JavaScript代碼之前運行第一個要求:

Array = function(){ 
    alert('Mwahahahaha'); 
}; 

此外, Cooper要求必須將自定義函數添加到Array內建的對象中(而不是被劫持的對象)。例如,如果Array被unhijacked,這將是與完成:

Array.prototype.coolCustomFunction = function(){ 
    alert('I have ' + this.length + ' elements! Cool!'); 
}; 

這將提供:

var myArray = []; 
myArray.coolCustomFunction(); 

然而,這不符合第一項要求相兼容。因此,你如何能夠最好地滿足D.B.庫珀的要求?

注意: D.B.甚至寫了a test fiddle幫助確保解決方案符合他的要求......真是個好人!


更新: 對於那些你們誰喜歡挑戰:請嘗試找到一個unhijackable跨瀏覽器解決了這個問題。例如,here's是劫持Array,Object,Array.prototype.constructor和Object.prototype.constructor的更劫持的測試用例(感謝重新格式化此Bergi)。到目前爲止,看起來似乎可能有針對瀏覽器的解決方案(請參閱Bergi's comment on his answer,如果您在FF中找到劫持它的方法,請告訴我們),但目前還不清楚是否存在跨瀏覽器解決這個問題。

+2

這個問題的格式應SO – rjz 2012-07-17 16:48:38

+2

需要學習材料新海報發送需求文檔回到DB Cooper和堅持使用情況的每一個需求。 :) – Quentin 2012-07-17 16:59:33

+0

@Quentin:如果你能找到他,那將是一個不錯的選擇:) – Briguy37 2012-07-17 17:15:33

回答

2

無論您Array功能/構造函數,數組字面語法,則始終會與他們的「真正的」陣列[[原型]設置爲本地數組原型對象(一次,這was a security vulnerability)。所以,你可以隨時訪問,通過使用

Object.getPrototypeOf([]) 

即使Array[].constructor被劫持。如果你想用一種變通方法,in FF下面的行會一直工作(當Object被劫持當然不會工作,那麼它獲得的非常複雜)

Brought D.B. down!


(而不是hijackable):

[].__proto__.coolCustomFunction = coolCustomFunction; 
+0

有趣!我決定嘗試劫持數組對象的構造函數:'[] .constructor.prototype.constructor = ..',並導致Torsten的解決方案失敗。然後,我劫持了Object並導致你的解決方案失敗,但它適用於'({})。constructor'。然後我劫持了Object對象的構造函數:'({})。constructor.prototype.constructor = ..'這導致一切都失敗。在那一點上,我卡住了,所以我還沒有找到一個不可劫持的解決方案呢:)這是一個更新的小提琴:http://jsfiddle.net/briguy37/yXPJ8/8/ – Briguy37 2012-07-17 17:50:26

+1

這就是我的線的想法:-)然而,我已經[重建了你的重劫劫持](http://jsfiddle.net/yXPJ8/9/)更具可讀性。現在,你只能在FF中使用非標準的'__proto__'(我認爲是不可劫持的) – Bergi 2012-07-17 18:14:23

+0

非常好,我沒有看到在FF中劫持的方法!我仍然有興趣看看@ Torsten建議從一個新窗口對象或另一種方法獲取構造函數是否會導致跨瀏覽器不可劫持的解決方案。 – Briguy37 2012-07-17 18:50:29

1

是...你只是做了...但你創建使用[]數組。如果使用new Array()它工作正常...

See example here

+2

對不起,那不符合測試用例。你不能編輯它。 – Briguy37 2012-07-17 16:47:19

+0

@ Briguy37那麼它不能 - 你不能覆蓋'[]'函數 - 這指向一個內部構造函數 – ManseUK 2012-07-17 16:49:43

+0

這可能就是這種情況。但是,如果修改'Array'的原型以在劫持它之前添加函數,則可以在用'[]'創建的對象上使用該函數。因此,我想知道在Array被劫持後是否有辦法做到這一點。 – Briguy37 2012-07-17 16:53:54

3

由於Array不一定等於[].constructor ,您可以使用[].constructor來引用原始數組函數,因爲這是硬連線的,並且Array = function(){}不會改變它。

Array = function() { alert("foo")}; 

// this will always point to the original Array 
[].constructor.prototype.foo = "bar"; 

var myArray = [0, 1]; 
alert(myArray.foo) // alerts "bar" 

http://jsfiddle.net/yXPJ8/5/

+0

您的第一個解決方案使D.B.快樂:)(第二個違反他的第一個要求) – Briguy37 2012-07-17 17:04:34

+0

好吧,錯過了「之前任何其他」位。 ;) – 2012-07-17 17:09:13

+0

如果'arrayProto.constructor = wrongArray'會發生什麼? – Bergi 2012-07-17 17:33:34

相關問題