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?
4 Answers 4
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.
3 Comments
if (enumHash[someValue])if(enumHash[a.valueOf()]===true)" 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/… Wrong way to change system objects like Array, Object etc. Because conflicts may occur if anyone do such changes
Comments
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.
4 Comments
[" 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()]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.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.functin in_array(target, array) { return array.map(String).indexOf(String(target).trim()) !== -1 } then in_array('1', [ 1, 2, 3, 'hi' ])you can just use Array.prototype.indexOf(el)
[ 'value1', 'value2', 'value3', 'value4' ].indexOf(a.valueOf()) !== -1
1 Comment
Explore related questions
See similar questions with these tags.
return arr.indexOf(this.valueOf())