2012-07-17 52 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

相关问题