0

In my javascript code I often need to check if an expression in some enumerable list like this:

if ((a == 'value1') || (a == 'value2') || (a == 'value3')) { ... do smth ... }

I can write something like this:

if (['value1', 'value2', 'value3', 'value4'].indexOf ( a ) ) { ... do smth ... }

but I think it's unreadable.

I add property in_arr for Object.prototype:

Object.defineProperty(Object.prototype, 'in_arr', {
 value : function(arr) {
 for (var i=0; i<arr.length; i++) {
 if ( arr[i] == this.valueOf() ) {
 return true;
 }
 }
 return false;
 },
 enumerable: false
})

And now I can write like this:

if (a.in_arr([ 'value1', 'value2', 'value3', 'value4' ]) { ... do smth ... }

I think, it's looks good. But I want to ask: Is it safe to change Object.prototype like this? And what about perfomance?

asked Oct 30, 2013 at 14:29
4
  • No, you should not change Object's prototype. If everybody started doing this, JavaScript would be a complete minefield. Commented Oct 30, 2013 at 14:32
  • 1
    moreover, why your 'in_arr' code does not use the indexOf method of array ? return arr.indexOf(this.valueOf()) Commented Oct 30, 2013 at 14:48
  • an indexOf is perfectly readable and clear for any javascript developer and more clear than object prototyping in this case Commented Oct 30, 2013 at 15:11
  • @benzonico, sometimes I need to compare strings and numbers ('1' == 1 is right for my situation). ['1','2'].indexOf(1) return -1. Commented Oct 30, 2013 at 15:16

4 Answers 4

3

Create an enumeration hash, like this:

var enumHash = {
 value1: true,
 value2: true,
 value3: true
 // actually it doesn't matter which value to assign: 
 // even undefined will do, as you check the existence of a property, not its value
};

... then just check the existence of a property:

if (someValue in enumHash) { ... }

That'll be both faster than Array.indexOf and more readable.

answered Oct 30, 2013 at 14:51
Sign up to request clarification or add additional context in comments.

3 Comments

You could even do if (enumHash[someValue])
In the OP's case he can use if(enumHash[a.valueOf()]===true)
One situation that isn't covered is that " 1 "==1 the OP probably needs to create a polyfil for trim to make it behave the way he wants to: if(enumHash[a.valueOf().trim()]===true) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
0

Wrong way to change system objects like Array, Object etc. Because conflicts may occur if anyone do such changes

answered Oct 30, 2013 at 14:52

Comments

0

It's not recomended to extend Object.prototype, this will lead to strange behaviours and there is no need to do it one way if there is a less dangerous one like a simple function.

in_array(obj, [ 'a', 'b', 'c' ]);

You can even create a utils object

utils.in_array(obj, [ 'a', 'b', 'c' ]);

Once I've said that...

This looks very similar to Extending Object.prototype JavaScript and I totally agree with Alex Wayne:

I think it's fine if it works in your target environment.

Also I think prototype extension paranoia is overblown. As long as you use hasOwnProperty() like a good developer that it's all fine. Worst case, you overload that property elsewhere and lose the method. But that's your own fault if you do that.

answered Oct 30, 2013 at 22:25

4 Comments

If you have to do it then the most elegant way would be to polyfil the indexOf. But in the OP's case [" 1 "].indexOf(1) would return -1 (false) where " 1 "== 1 would return true. So best solution in my opinion would be to use raina's answer and polyfil trim: keys={1:true};keys[" 1 ".trim()]
Why whould you suppose OP's program need to parse un-trimmed strings? In any case, this can be easely added to the helper function functin in_array(target, array) { return array.indexOf(target.trim()) !== -1 }. By the way, if you use keys[value.trim()] if value is "constructor", "toString", "toValue" or any other property in Object.prototype it will return a false positive.
Quotes from op: if ((a == 'value1') || (a == 'value2') and I need to compare strings and numbers ('1' == 1 is right for my situation). ['1','2'].indexOf(1) return -1 As for the second part; I don't think so: var keys ={"1":true};console.log(keys["toString"]===true) (as used in reply to raina). I'm just saying that in my opinion raina's answer is more effective (would be mine but he beat me to it) and elegant to solve this particular problem.
Easier functin in_array(target, array) { return array.map(String).indexOf(String(target).trim()) !== -1 } then in_array('1', [ 1, 2, 3, 'hi' ])
-2

you can just use Array.prototype.indexOf(el)

[ 'value1', 'value2', 'value3', 'value4' ].indexOf(a.valueOf()) !== -1
answered Oct 30, 2013 at 14:47

1 Comment

Aren't the very same lines given in the question itself? Who and why upvoted this?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.