7

This question is related to What are the best practices to follow when declaring an array in Javascript?


Let's say a client, let's call them "D. B. Cooper", has a first requirement that the following code must run before any other JavaScript code:

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

Furthermore, Cooper requires that custom functions must be added to the built in Array object (not the hijacked one). For example, if Array was unhijacked, this would be done with:

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

Which would afford:

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

However, this is not compatible with the first requirement. Thus, how can you best fulfill both of D. B. Cooper's requirements?

Note: D.B. even wrote a test fiddle to help make sure solutions meet his requirements...what a guy!


Update: For those of you who like a challenge: please try to find an unhijackable cross-browser solution to this problem. For example, here's an even more hijacked test case (thanks for reformatting this Bergi) that hijacks Array, Object, Array.prototype.constructor, and Object.prototype.constructor. Thus far, it looks like there may be a browser-specific solution to this (see Bergi's comment on his answer, and let us know if you find a way to hijack it in FF), but it is unclear at this point if there is a cross-browser solution to this.

3
  • 2
    The format of this question should be required study material for new posters on SO Commented Jul 17, 2012 at 16:48
  • 2
    Send the requirements document back to D. B. Cooper and insist on use cases for every demand. :) Commented Jul 17, 2012 at 16:59
  • @Quentin: If you can find him, that would be a good option :) Commented Jul 17, 2012 at 17:15

3 Answers 3

3

Whatever your Array function/constructor is, the literal syntax for arrays will always generate "real" arrays with their [[prototype]] set to the native array prototype object (once, this was a security vulnerability). So, you can always access that by using

Object.getPrototypeOf([])

even if Array or [].constructor are hijacked. (Will of course not work when Object is hijacked, then it get's really complicated)

(Brought D.B. down!)


If you want to use a workaround, in FF the following line will always work (and is not hijackable):

[].__proto__.coolCustomFunction = coolCustomFunction;
Sign up to request clarification or add additional context in comments.

4 Comments

Interesting! I decided to try hijacking the constructor of the array object: [].constructor.prototype.constructor = .., and that caused Torsten's solution to fail. Then, I hijacked Object and that caused your solution to fail, but it works with ({}).constructor. Then I hijacked the constructor of the Object object: ({}).constructor.prototype.constructor = .. which caused everything to fail. At that point, I'm stuck, so I haven't found an un-hijackable solution to this yet :) Here's an updated fiddle: jsfiddle.net/briguy37/yXPJ8/8
That was exactly my line of thought :-) However, I've restructed your heavy-hijacked fiddle to be more readable. Now, you can only use non-standard __proto__ in FF (unhijackable, I think)
Very nice, I don't see a way to hijack that in FF either! I'm still interested to see if @Torsten's suggestion to get the constructor from a new window object or another method could lead to a cross-browser un-hijackable solution to this.
Actually, __proto__ is just a getter/setter property not a built-in. You can delete Object.prototype.__proto__.
3

Since Array is not necessarily equal to [].constructor, you could use [].constructor to refer to the original Array function since this is hardwired and Array = function(){} won't alter it.

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/

7 Comments

Your first solution makes D.B. happy :) (the second would violate his first requirement)
Okay, missed the "before any other" bit. ;)
[].constructor = function(){}; still only refers to the constructor of that instance. a subsequent call to [].constructor would have an intact reference since it is created new for each instance. You could however try to overwrite the constructor.prototype which would do nothing since it is protected (unless the JS engine is broken).
@Bergi Nice catch - Interestingly enough even though Array.prototype.constructor will point to a different function creating an array still works. If you remove all the references to the prototype's constructor, then of course there is no way to get it back without reloading the page or opening a new window and getting it from there. var win = window.open(); Array.prototype.constructor = win.Array.prototype.constructor;
@TorstenWalter: Although I can't get it to work. Can you demonstrate this in here?
|
1

Yes ... you just did ... but you created the array using [] .. if you use new Array() it works fine ...

See example here

3 Comments

Sorry, that does not fulfill the test case. You are not allowed to edit it.
@Briguy37 then it cant - you cannot overwrite the [] function - this points to an internal constructor
That may very well be the case. However, if you modify Array's prototype to add a function before you hijack it, you can use that function on an object created with []. Thus, I was wondering if there was a way to do this after Array was hijacked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.