-1

Ok, so I've blocked myself in with a stupid move that is now causing conflict with the jQuery library I am using, and well I should say rather is likely breaking more than just that after the reading I have done. Anyway I was attempting to use the following bit:

Array.prototype.contains = function(v) {
    for(var i = 0; i < this.length; i++) {
        if(this[i] === v) return true;
    }
    return false;
};

Array.prototype.unique = function() {
    var arr = [];
    for(var i = 0; i < this.length; i++) {
        if(!arr.contains(this[i])) {
            arr.push(this[i]);
        }
    }
    return arr;
}

To get the unique values of an array however, this ended up causing a conflict for jQuery in my cause breaks a lot of things, So how can I get around the forbidden yet tasty idea of using prototype? Specifically in this case of needing to the unique values in an array?

chris
  • 36,115
  • 52
  • 143
  • 252
  • Can you use a library such as Underscore? – Brian Lewis Apr 21 '14 at 18:08
  • 1
    this is a more simplified approach - why not just change the names of your prototype methods to something like "hascontent" or "isunique"? – james emanon Apr 21 '14 at 18:09
  • 2
    Conflicting in what way? Do you get errors? Do you have an example? – Explosion Pills Apr 21 '14 at 18:09
  • 1
    jQuery does not modify any built in prototypes. So this code should not conflict with it. What, specifically is the problem ou are observing? – Alex Wayne Apr 21 '14 at 18:13
  • If you're using `for-in` on an Array, that could break things. But this has nothing to do with jQuery. It has to do with not knowing how to properly iterate an Array. – cookie monster Apr 21 '14 at 18:13
  • @cookiemonster: jQuery has some parts that do not know how to iterate an array, and therefore do break. – Bergi Apr 21 '14 at 19:07
  • related: [How to define method in javascript on Array.prototype and Object.prototype so that it doesn't appear in for in loop](http://stackoverflow.com/q/13296340/1048572) – Bergi Apr 21 '14 at 19:08
  • @Bergi: Can you provide an example of how extending `Array.prototype` will break jQuery? I know they don't use `.hasOwnProperty()` when using `for-in`. So are you saying they use `for-in` on Arrays? That would surprise me. – cookie monster Apr 21 '14 at 19:24
  • @cookiemonster: There are some places where both objects and arrays can be passed, and they use `for in`. I remember that `$.param` or something (called from `$.ajax`) bit me once… – Bergi Apr 21 '14 at 19:26
  • @Bergi: I see. I know their `each` style methods check Array[-like] objects, and then uses `for` if possible. It surprises me that they don't always do that. – cookie monster Apr 21 '14 at 19:31

1 Answers1

1

A common way to avoid modifying prototypes of native types is static methods:

Array.unique = function( entity ) {
    // do your stuff
};

// example call
var unique = Array.unique( [1, 1, 2, 3] );

Or, to take it one step further, even do something like this

var Arrays = Arrays || {};
Arrays.unique = function( entity ) { /* … */ };

This way you are completely separated from the built-in Array.

Ingo Bürk
  • 19,263
  • 6
  • 66
  • 100
  • 1
    "static" methods on built-in constructors can conflict with other code too. – cookie monster Apr 21 '14 at 18:14
  • @cookiemonster I added a slight variation (which I prefer anyway). – Ingo Bürk Apr 21 '14 at 18:15
  • 1
    The only real way to make that safe would be to declare it inside a function that contains the rest of the code. If it's global, you could have the same issue. Though I have no idea what conflict the OP is talking about in the first place. – cookie monster Apr 21 '14 at 18:17
  • 1
    ...ultimately, the only real solution is to understand exactly how every bit of code one loads affects the environment, and if it affects it in an undesirable way, don't load it. – cookie monster Apr 21 '14 at 18:18
  • If one of your library already defines `Arrays`, you should know about it. If it doesn't, there shouldn't be any interference. Eventually you can take this argument against everything – at some point you need *some* globally available name, even if you encapsulated your entire application into one module … which could, theoretically, interfere. So I see the danger when doing anything with built-ins, but using `Arrays` really should be safe enough. – Ingo Bürk Apr 21 '14 at 18:19
  • And that's my point. The only real solution is to understand exactly how every bit of code one loads affects the environment. Doesn't matter if it's defining global or extending built in `.prototype` objects. It's all the same issue. – cookie monster Apr 21 '14 at 18:25
  • But the chances are quite different. It's like writing your own library and naming the instance `$`. Sure it's "just as dangerous" as naming it `MyAwesomeLibraryThingy`, but *chances* are that the latter will cause a conflict much more rarely (the best way being a `noConflict` API, but it's just an example). – Ingo Bürk Apr 21 '14 at 18:27
  • Nothing should be left to chance. I don't understand arguments that favor being unaware of what the code you load does. – cookie monster Apr 21 '14 at 18:30
  • That's a misunderstanding. I completely agree that you should be aware of what is happening. But your argument against my answer is possible interference. I see that point when manipulating built-in types in any way, but using custom names I think it's a poor argument. By that logic, almost every answer on SO should be commented with "could lead to interference". Some things you just want globally available and I think common helpers like these are a good example. Afterall that's what jQuery, underscore etc. do, too. – Ingo Bürk Apr 21 '14 at 18:40
  • Yes, I'm not arguing against using globals any more than I'm arguing against extending prototypes. The OP says he has a conflict with jQuery *(which doesn't really make sense)*, so I'm just saying that the ultimate way to avoid conflict is to understand the code one uses before using it. +1 for a reasonable alternative. – cookie monster Apr 21 '14 at 18:43
  • Yes, I definitely agree on that! – Ingo Bürk Apr 21 '14 at 19:11