4

My app (a custom web browser) is injecting code into a page that has a modified Array prototype (specifically because it uses prototype.js). I would like to ensure that the code I inject uses the normal Array. I am using the code from https://stackoverflow.com/a/15147986/502149 to reset the prototype, and this works fine if I say:

(function(Array) {
  var array = new Array();
)(ArrayWithUnmodifiedPrototype);

However, I still get the modified prototype if I say:

(function(Array) {
  var array = [];
)(ArrayWithUnmodifiedPrototype);

I'm not sure if this is going to be a problem (some third-party libraries in the code I inject could theoretically use []) but either way I'm curious: is there any way to override [] so it uses a different prototype than that of the current Array.prototype in global scope?

Community
  • 1
  • 1
Matthew Gertner
  • 4,487
  • 2
  • 32
  • 54
  • I don't believe it's possible. – Felix Kling Aug 01 '14 at 16:40
  • maybe one of the reasons why messing with builtin prototypes is a bad practice – MightyPork Aug 01 '14 at 16:40
  • That's why you don't modify native prototypes. – Derek 朕會功夫 Aug 01 '14 at 16:41
  • FWIW, you shouldn't *need* to do this, not just with the modifications PrototypeJS makes to `Array.prototype`. As long as you're [looping through arrays *correctly*](http://stackoverflow.com/questions/9329446/how-to-do-for-each-over-an-array-in-javascript/9329476#9329476), the new stuff doesn't do much harm. (I say "much" because last I checked, it had a bad habit of overwriting native implementations of things...) – T.J. Crowder Aug 01 '14 at 16:46

1 Answers1

4

No, there isn't. This is actually one of the good things about using literals. :-) But in your particular unusual situation, it's less helpful.

Just for completeness:

Given that you do apparently have a reference to an Array.prototype that isn't modified (I'm basing this on your ArrayWithUnmodifiedPrototype symbol), you could get around this by swapping things each time you need to create an array or call one of those third-party libraries. (This is obviously less than ideal.)

E.g.:

var oldPrototype = Array.prototype;
Array.prototype = ArrayWithUnmodifiedPrototype.prototype;
/*...call third-party lib that might use []...*/
Array.prototype = oldPrototype;

But if the third-party stuff is processing things in ajax callbacks and such, you'd probably struggle to slip your code in to swap the prototypes around.

Probably the best thing is to ensure the code you inject works with any reasonable modifications to Array.prototype (such as the ones PrototypeJS does, which are mostly reasonable despite the fact it still overwrites things like Array.prototype.map even if they're there...).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • The problem is that we are dealing with libraries that we don't control in both the webpage and injected code. The webpage might modify the `Array` prototype because it uses prototype.js and we might be using e.g. Underscore.js in our injected code. The safest thing is to ensure that the injected code sees unmodified prototypes for all built-in types (like Chrome extensions do). In my experience, Murphy's Law applies to the web: if something can break, it will. Unfortunately it seems like this isn't possible in the case of literals. Hopefully this won't turn out to be a problem in practice. – Matthew Gertner Aug 04 '14 at 10:19