Created
August 20, 2011 08:32
-
-
Save WebReflection/1158853 to your computer and use it in GitHub Desktop.
implementing "in" operator as generic object method
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(Object, String){ | |
// (C) WebReflection - Mit Style License | |
// @about implementing "in" operator as generic object method | |
// returns primitive value or object itself | |
function toValue(obj) { | |
switch (true) { | |
case isInstanceOf(obj, Boolean): | |
case isInstanceOf(obj, Number): | |
case isInstanceOf(obj, String): | |
return obj.valueOf(); | |
default: | |
return obj; | |
} | |
} | |
// reduce occurrences of "instanceof" for minified code | |
function isInstanceOf(obj, constructor) { | |
return obj instanceof constructor; | |
} | |
var // block of private variables | |
// used to grab indeOf and toString | |
// should be trashed automatically | |
array = [], | |
// quirk implementation, enough here | |
indexOf = array.indexOf || function (value) { | |
var i = this.length; | |
while (i-- && this[i] !== value) {} | |
return i; | |
}, | |
// minifiers shortcuts | |
proto = Object.prototype, | |
toString = proto.toString, | |
floor = Math.floor, | |
FALSE = false, | |
// make it compatible with different | |
// JS implementations, Rhino too | |
ARRAY = toString.call(array) | |
; | |
// do not redefine if present | |
"in" in proto || Object.defineProperty(proto, "in", { | |
// force defaults (just in case) | |
writable: FALSE, | |
enumerable: FALSE, | |
configurable: FALSE, | |
// the "in" method | |
value: function (obj) { | |
var | |
// reused later on | |
value, key, | |
// minifiers shortcut | |
self = this | |
; | |
// operation is both context | |
// and argument dependent | |
switch (typeof obj) { | |
// obj is Array or generic Object | |
case "object": | |
// "value".in(["some", "value"]); // true | |
if (toString.call(obj) === ARRAY) { | |
return -1 < indexOf.call(obj, toValue(self)); | |
} | |
// "value".in({some: "value"}); // true | |
value = toValue(self); | |
for (key in obj) { | |
// inherited too as is for "in" operator | |
if (obj[key] === value) { | |
return true; | |
} | |
} | |
return FALSE; | |
//* hard to say if anything that's not object | |
// should accepted as "in" argument | |
// if you think so, comment out this part | |
// just removing first slash of this comment | |
case "string": | |
// "bc".in("abcd"); // true | |
if (isInstanceOf(self, String)) { | |
return -1 < obj.indexOf(self); | |
} | |
case "number": | |
// (3).in(15); // true as part of gcd | |
if (isInstanceOf(self, Number)) { | |
value = obj / self; | |
return floor(value) === value; | |
} | |
//*/ | |
} | |
return FALSE; | |
} | |
}); | |
}(Object, String)); | |
/* da test, add a sash to perform the test => //* rather than /* | |
alert([ | |
0 in [3,4,5], // true, index 0 exists | |
(4).in([3,4,5]), // true, array contains value 0 | |
(3).in(15), // true, 15 can be divided by 3 | |
3..in({three: 3}), // true, object has a property with value 3 | |
"three" in {three: 3}, // true, three as property name | |
"bc".in("abcd"), // true, string "abcd" contains "bc" | |
"b".in(["a","b","c"]), // true, array contains value "b" | |
"b".in({a:"b"}), // true, object has no property with value "b" | |
(0).in([3,4,5]), // false, array does not contain value 0 | |
(2).in({three: 3}), // false, object has no property with value 2 | |
"three".in({three: 3}), // false, object has no property with value "three" | |
"b" in ["a","b","c"] // false, b is not a valid index | |
].join("\n")); | |
//*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment