I need to do operations like compare that two number arrays have the same values, or two objects have the same member values. Is there a method that does this for me already (either ECMAScript or jQuery)?
For example, the function should return true that these both are the same:
var a = [1,2,3,4];
var b = [1,2,3,4];
Or with objects, the function should return that these two are the same:
var a = { id: 99, name: "Chris" };
var b = { name: "Chris", id: 99 };
I'm thinking maybe just JSON.stringify(a) === JSON.stringify(b)? Any problem with that?
Try the equiv library by Philippe Rathé. (Unfortunately the main site seems to be down, so I linked to js-test-driver source.)
Here's a pretty silly way to compare two objects containing scalar values:
function same(object1, object2) {
var merged = $.extend({}, object1, object2);
for (var key in merged) {
if (!object1.hasOwnProperty(key) ||
!object2.hasOwnProperty(key) ||
object1[key] != merged[key]) {
return false;
}
}
return true;
}
It relies on jQuery's extend and fails if object2 inherits properties from a prototype, since extend copies those, too.
function areEquiv ( a, b ) {
var eqCount = 0,
sizeCount = 0,
othCount = 0,
i;
if (typeof a.concat === "function") { // if comparing arrays
for (i = 0; i < a.length; i++) {
othCount = sizeCount = sizeCount + 1;
if (a[i] === b[i]) eqCount++;
}
} else { // if comparing objects
for (i in a) {
if (a.hasOwnProperty(i)) {
sizeCount = sizeCount + 1;
if (a[i] === b[i]) eqCount++;
}
}
for (i in b) {
if (b.hasOwnProperty(i)) {
othCount = othCount + 1;
}
}
}
return (a.length == b.length && eqCount == sizeCount && sizeCount == othCount);
}
Note that this will only work as long as the array or object contains simple values and isn't an array of objects or object with a parameter that's also an object.
Related
I have an an array which is mentioned below. I would like to remove an item from the array which has empty property value using JavaScript.
Actual array:
[
{
"href":"/client",
"methods":[]
},
{
"href":"/home",
"methods":
{
"type1":"GET",
"type2":"POST",
}
},
{
"href":"/about",
"methods":[]
},
{
"href":"/contact",
"methods":
{
"type1":"GET",
"type2":"POST",
}
}
]
Expecting result:
[
{
"href":"/home",
"methods":
{
"type1":"GET",
"type2":"POST",
}
},
{
"href":"/contact",
"methods":
{
"type1":"GET",
"type2":"POST",
}
}
]
This is the job for filter. however filter does not modify the existing array so you need to assign it to a different array/overwrite the current variable
a = a.filter(item => Object.keys(item.methods).length > 0)
Iterate over the object array and filter based on methods property length.
var obj = [...];
obj = obj.filter((val) => val.methods && val.methods.length !== 0);
In the case of methods, you can easily walk the object and then call delete on the keys with values that are empty.... or empty arrays. I expanded the answer to cover not only keys of methods where an array is empty, but all keys with what i would define as empty contents.
var l = [];
for (var i = 0; i < l.length; i++){
var keys = Object.keys(l[i]);
for ( var j = 0; j < keys.length; j++){
var value = keys[j];
// In your use case, you are only doing arrays so i coded it as such.
if (value.length == 0){
delete l[i][j];
}
}
}
If you want to expand it to cover a variety of cases such as empty string, empty arrays, empty maps, or null values you can defined a function to do that.
function isValueDeletable(value){
if (value == null) return true;
if (value == "") return true;
if (value instanceof Array && value.length == 0) return true;
if (value instanceof Map && Object.keys(value).length == 0) return true;
return false;
}
and apply that instead of the value.length == 0;
if (isValueDeletable(value)){ delete l[i][j]; }
Then l is modified to remove all keys with empty values.
enter var json = {};
var key = "giveitakeyvalue";
json[key] = null;
delete json[key];
Is there a way to return the difference between two arrays in JavaScript?
I can not use indexOf in this case.
For example:
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
// need [{"c":"C"}]
Please advise.
One object can never be the same as another object even if they have the same content. They would still be different instances of Objects.
That means you have to compare keys and values to check that they match, or in this case, don't match.
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
var a3 = a2.filter(function(o) {
return Object.keys(o).some(function(k) {
return a1.every(function(o2) {
return !(k in o2) || (o2[k] != o[k]);
});
});
});
FIDDLE
As I mentioned in my comment, objects are only equal if they refer to the same instance. Therefore, any built-in system will not do, least of all == and ===. So, first you must define your own comparison function.
Let's say that two objects are equal if they contain the same keys with the same values.
function areObjectsEqual(a,b) {
function helper(a,b) {
var k;
for( k in a) {
if( a.hasOwnProperty(k)) {
if( !b.hasOwnProperty(k)) return false;
if( typeof a[k] != typeof b[k]) return false;
if( typeof a[k] == "object") {
if( !areObjectsEqual(a[k],b[k])) return false;
// the above line allows handling of nested objects
}
else {
if( a[k] != b[k]) return false;
// this comparison is technically strict
// because we already checked typeof earlier
}
}
}
}
return helper(a,b) && helper(b,a);
}
Okay, now that that's out of the way, we can compare our functions.
function array_diff(a,b) {
var result = [], l = a.length, i, m = b.length, j;
outer:
for( i=0; i<l; i++) {
for( j=0; j<m; j++) {
if( typeof a[i] != typeof b[j]) continue;
if( typeof a[i] == "object") {
if( !areObjectsEqual(a[i],b[j])) continue;
}
else {
if( a[i] != b[j]) continue;
}
// if we got to here, it's a match!
// ... so actually we want to skip over the result :p
continue outer;
}
// okay, if we get HERE then there was no match,
// because we skipped the "continue outer"
result.push(a[i]);
}
return result;
}
And there you go!
Easy and simple way to achieve your goal
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"c":"C"},{"b":"B"}];
var max = (a1.length > a2.length) ? a1 : a2;
var min = (a1.length > a2.length) ? a2 : a1;
var newArray = [];
for ( var i = 0; i < max.length; i++ ) { // saving elements into string
max[i] = JSON.stringify(max[i]);
if ( typeof min[i] !== undefined ) {
min[i] = JSON.stringify(min[i]);
}
}
for ( var i = 0; i < max.length; i++ ) { // checking values uniqueness
if ( min.indexOf(max[i]) === -1 ) {
newArray.push(max[i]);
}
}
// if you need new Array's elements back in object do following iteration
for ( var i in newArray ) { // loop recreate results array's elements into object again
newArray[i] = JSON.parse(newArray[i]);
}
console.log(newArray); // result : [Object { c="C"}]
JSFiddle
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
var obj = {}, result = [];
function updateObjectCount(currentItem) {
var keys, key;
for (key in currentItem) {
if (currentItem.hasOwnProperty(key)) {
keys = key;
break;
}
}
obj[key] = obj[key] || {};
obj[key][currentItem[key]] = (obj[key][currentItem[key]] || 0) + 1;
}
a1.forEach(updateObjectCount);
a2.forEach(updateObjectCount);
for (var key1 in obj) {
if (obj.hasOwnProperty((key1))) {
for (var key2 in obj[key1]) {
if (obj.hasOwnProperty((key1))) {
if (obj[key1][key2] === 1) {
var temp = {};
temp[key1] = key2;
result.push(temp)
}
}
}
}
}
console.log(result);
# [ { c: 'C' } ]
I have array with objects.
Something Like this:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
When I try:
arr.indexOf({x:1, y:2});
It returns -1.
If I have strings or numbers or other type of elements but object, then indexOf() works fine.
Does anyone know why and what should I do to search object elements in array?
Of course, I mean the ways except making string hash keys for objects and give it to array...
indexOf compares searchElement to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator).
You cannot use === to check the equability of an object.
As #RobG pointed out
Note that by definition, two objects are never equal, even if they have exactly the same property names and values. objectA === objectB if and only if objectA and objectB reference the same object.
You can simply write a custom indexOf function to check the object.
function myIndexOf(o) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].x == o.x && arr[i].y == o.y) {
return i;
}
}
return -1;
}
DEMO: http://jsfiddle.net/zQtML/
As nobody has mentioned built-in function Array.prototype.findIndex(), I'd like to mention that it does exactly what author needs.
The findIndex() method returns the index of the first element in the
array that satisfies the provided testing function. Otherwise -1 is
returned.
var array1 = [5, 12, 8, 130, 44];
function findFirstLargeNumber(element) {
return element > 13;
}
console.log(array1.findIndex(findFirstLargeNumber));
// expected output: 3
In your case it would be:
arr.findIndex(function(element) {
return element.x == 1 && element.y == 2;
});
Or using ES6
arr.findIndex( element => element.x == 1 && element.y == 2 );
More information with the example above: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
As noted, two objects are never equal, but references can be equal if they are to the same object, so to make the code do what you want:
var a = {x:1, y:2};
var b = {x:3, y:4};
var arr = [a, b];
alert(arr.indexOf(a)); // 0
Edit
Here's a more general specialIndexOf function. Note that it expects the values of the objects to be primitives, otherwise it needs to be more rigorous.
function specialIndexOf(arr, value) {
var a;
for (var i=0, iLen=arr.length; i<iLen; i++) {
a = arr[i];
if (a === value) return i;
if (typeof a == 'object') {
if (compareObj(arr[i], value)) {
return i;
}
} else {
// deal with other types
}
}
return -1;
// Extremely simple function, expects the values of all
// enumerable properties of both objects to be primitives.
function compareObj(o1, o2, cease) {
var p;
if (typeof o1 == 'object' && typeof o2 == 'object') {
for (p in o1) {
if (o1[p] != o2[p]) return false;
}
if (cease !== true) {
compareObj(o2, o1, true);
}
return true;
}
}
}
var a = new String('fred');
var b = new String('fred');
var arr = [0,1,a];
alert(specialIndexOf(arr, b)); // 2
This works without custom code
var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true
Note: this does not give the actual index, it only tells if your object exists in the current data structure
Those objects aren't equal.
You must implement your own function.
You may do that for example :
var index = -1;
arr.forEach(function(v, i) {
if (this.x==v.x && this.y==v.y) index=i;
}, searched);
where searched is one of your object (or not).
(I would implement it with a simple loop but it's prettier with foreach)
Because two separate objects are not === to each other, and indexOf uses ===. (They're also not == to each other.)
Example:
var a = {x:1, y:2};
var b = {x:1, y:2};
console.log(a === b);
=== and == test for whether their operands refer to the same object, not if they refer to equivalent objects (objects with the same prototype and properties).
Here's another solution, where you pass a compare function as a parameter :
function indexOf(array, val, from, compare) {
if (!compare) {
if (from instanceof Function) {
compare = from;
from = 0;
}
else return array.__origIndexOf(val, from);
}
if (!from) from = 0;
for (var i=from ; i < array.length ; i++) {
if (compare(array[i], val))
return i;
}
return -1;
}
// Save original indexOf to keep the original behaviour
Array.prototype.__origIndexOf = Array.prototype.indexOf;
// Redefine the Array.indexOf to support a compare function.
Array.prototype.indexOf = function(val, from, compare) {
return indexOf(this, val, from, compare);
}
You can then use it these way:
indexOf(arr, {x:1, y:2}, function (a,b) {
return a.x == b.x && a.y == b.y;
});
arr.indexOf({x:1, y:2}, function (a,b) {
return a.x == b.x && a.y == b.y;
});
arr.indexOf({x:1, y:2}, 1, function (a,b) {
return a.x == b.x && a.y == b.y;
});
The good thing is this still calls the original indexOf if no compare function is passed.
[1,2,3,4].indexOf(3);
Looks like you weren't interested in this type of answer, but it is the simplest to make for others who are interested:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
arr.map(function(obj) {
return objStr(obj);
}).indexOf(objStr({x:1, y:2}));
function objStr(obj) {
return "(" + obj.x + ", " + obj.y + ")"
}
I have two or more javascript objects. I want to merge them adding values of common properties and then sort them in descending order of values.
e.g.
var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
var c = merge(a,b)
c should then be like this:
c = {
fr: 24,
en: 13,
in:9,
br:8
}
i.e. both objects are merge, values of common keys are added and then keys are sorted.
Here's what I've tried:
var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
c = {}
// copy common values and all values of a to c
for(var k in a){
if(typeof b[k] != 'undefined'){
c[k] = a[k] + b[k]
}
else{ c[k] = a[k]}
}
// copy remaining values of b (which were not common)
for(var k in b){
if(typeof c[k]== 'undefined'){
c[k] = b[k]
}
}
// Create a object array for sorting
var arr = [];
for(var k in c){
arr.push({lang:k,count:c[k]})
}
// Sort object array
arr.sort(function(a, b) {
return b.count - a.count;
})
but I dont think its good. So many loops :( It would be nice if someone can provide a less messy and good code.
In ES2015+, object properties are ordered (first by ascending numeric keys, then by insertion order for non-numeric keys). This is guaranteed by the specification if you use one of the methods for which iteration order is specified (like Object.getOwnPropertyNames).
In ES2020+, the methods for which enumeration order used to be unspecified are now specified (though environments have been following it for ages anyway).
But you have to be sure that none of the properties are numeric (otherwise, they'll come first, before non-numeric properties, no matter the insertion order).
Use reduce to iterate over each object and create or add to the same property on the accumulator. Then, sort the object's entries, and use Object.fromEntries to transform it into an object with sorted properties. No need for jQuery:
var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
console.log(merge(a, b));
function merge(...objects) {
const merged = objects.reduce((a, obj) => {
Object.entries(obj).forEach(([key, val]) => {
a[key] = (a[key] || 0) + val;
});
return a;
}, {});
return Object.fromEntries(
Object.entries(merged).sort(
(a, b) => b[1] - a[1]
)
);
}
It is not possible to sort the properties of an object, you can however sort an array:
var merged = $.extend({}, a);
for (var prop in b) {
if (merged[prop]) merged[prop] += b[prop];
else merged[prop] = b[prop];
}
// Returning merged at this point will give you a merged object with properties summed, but not ordered.
var properties = [];
for (var prop in merged) {
properties.push({
name: prop,
value: merged[prop]
});
}
return properties.sort(function(nvp1, nvp2) {
return nvp1.value - nvp2.value;
});
EDIT - i modified the script, this merges the properties if they are of the same type: numbers are summed, strings are concatenated and objects are recursively merged. I didn't include sorting because (quoting this answer Sorting JavaScript Object by property value)
JavaScript objects are unordered by definition (see the ECMAScript
Language Specification, section 8.6). The language specification
doesn't even guarantee that, if you iterate over the properties of an
object twice in succession, they'll come out in the same order the
second time.
If you need things to be ordered, use an array and the
Array.prototype.sort method.
function is_object(mixed_var) {
if (Object.prototype.toString.call(mixed_var) === '[object Array]') {
return false;
}
return mixed_var !== null && typeof mixed_var == 'object';
}
function merge(a, b) {
var cache = {};
cache = unpackObject(a, cache);
cache = unpackObject(b, cache);
return cache;
}
function unpackObject(a, cache) {
for (prop in a) {
if (a.hasOwnProperty(prop)) {
if (cache[prop] === undefined) {
cache[prop] = a[prop];
} else {
if (typeof cache[prop] === typeof a[prop]) {
if (is_object(a[prop])) {
cache[prop] = merge(cache[prop], a[prop]);
} else {
cache[prop] += a[prop];
}
}
}
}
}
return cache;
}
var a = {
en: 5,
fr: 3,
in : 9,
lang: "js",
object: {nestedProp: 6}
}
var b = {
en: 8,
fr: 21,
br: 8,
lang: "en",
object: {nestedProp: 1, unique: "myne"}
}
var c = merge(a, b);
fiddle here http://jsfiddle.net/vyFN8/1/
Here is my attempt, which is recursive for nested objects - https://gist.github.com/greenafrican/19bbed3d8baceb0a15fd
// Requires jQuery
// Merge nested objects and if the properties are numbers then add them together, else
// fallback to jQuery.extend() result
function mergeObjectsAdd(firstObject, secondObject) {
var result = $.extend(true, {}, firstObject, secondObject);
for (var k in result) {
if ("object" === typeof result[k]) {
firstObject[k] = firstObject[k] || {};
secondObject[k] = secondObject[k] || {};
result[k] = mergeObjectsAdd(firstObject[k], secondObject[k]);
} else {
firstObject[k] = firstObject[k] || 0;
secondObject[k] = secondObject[k] || 0;
result[k] = ("number" === typeof firstObject[k] && "number" === typeof secondObject[k]) ? (firstObject[k] + secondObject[k]) : result[k];
}
}
return result;
}
This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 6 years ago.
What is the best way to find if an object is in an array?
This is the best way I know:
function include(arr, obj) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == obj) return true;
}
}
console.log(include([1, 2, 3, 4], 3)); // true
console.log(include([1, 2, 3, 4], 6)); // undefined
As of ECMAScript 2016 you can use includes()
arr.includes(obj);
If you want to support IE or other older browsers:
function include(arr,obj) {
return (arr.indexOf(obj) != -1);
}
EDIT:
This will not work on IE6, 7 or 8 though. The best workaround is to define it yourself if it's not present:
Mozilla's (ECMA-262) version:
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(searchElement /*, fromIndex */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (len === 0)
return -1;
var n = 0;
if (arguments.length > 0)
{
n = Number(arguments[1]);
if (n !== n)
n = 0;
else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
if (n >= len)
return -1;
var k = n >= 0
? n
: Math.max(len - Math.abs(n), 0);
for (; k < len; k++)
{
if (k in t && t[k] === searchElement)
return k;
}
return -1;
};
}
Daniel James's version:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
roosteronacid's version:
Array.prototype.hasObject = (
!Array.indexOf ? function (o)
{
var l = this.length + 1;
while (l -= 1)
{
if (this[l - 1] === o)
{
return true;
}
}
return false;
} : function (o)
{
return (this.indexOf(o) !== -1);
}
);
If you are using jQuery:
$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);
For more information: http://api.jquery.com/jQuery.inArray/
First, implement indexOf in JavaScript for browsers that don't already have it. For example, see Erik Arvidsson's array extras (also, the associated blog post). And then you can use indexOf without worrying about browser support. Here's a slightly optimised version of his indexOf implementation:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
It's changed to store the length so that it doesn't need to look it up every iteration. But the difference isn't huge. A less general purpose function might be faster:
var include = Array.prototype.indexOf ?
function(arr, obj) { return arr.indexOf(obj) !== -1; } :
function(arr, obj) {
for(var i = -1, j = arr.length; ++i < j;)
if(arr[i] === obj) return true;
return false;
};
I prefer using the standard function and leaving this sort of micro-optimization for when it's really needed. But if you're keen on micro-optimization I adapted the benchmarks that roosterononacid linked to in the comments, to benchmark searching in arrays. They're pretty crude though, a full investigation would test arrays with different types, different lengths and finding objects that occur in different places.
If the array is unsorted, there isn't really a better way (aside from using the above-mentioned indexOf, which I think amounts to the same thing). If the array is sorted, you can do a binary search, which works like this:
Pick the middle element of the array.
Is the element you're looking for bigger than the element you picked? If so, you've eliminated the bottom half of the array. If it isn't, you've eliminated the top half.
Pick the middle element of the remaining half of the array, and continue as in step 2, eliminating halves of the remaining array. Eventually you'll either find your element or have no array left to look through.
Binary search runs in time proportional to the logarithm of the length of the array, so it can be much faster than looking at each individual element.
[ ].has(obj)
assuming .indexOf() is implemented
Object.defineProperty( Array.prototype,'has',
{
value:function(o, flag){
if (flag === undefined) {
return this.indexOf(o) !== -1;
} else { // only for raw js object
for(var v in this) {
if( JSON.stringify(this[v]) === JSON.stringify(o)) return true;
}
return false;
},
// writable:false,
// enumerable:false
})
!!! do not make Array.prototype.has=function(){... because you'll add an enumerable element in every array and js is broken.
//use like
[22 ,'a', {prop:'x'}].has(12) // false
["a","b"].has("a") // true
[1,{a:1}].has({a:1},1) // true
[1,{a:1}].has({a:1}) // false
the use of 2nd arg (flag) forces comparation by value instead of reference
comparing raw objects
[o1].has(o2,true) // true if every level value is same
It depends on your purpose. If you program for the Web, avoid indexOf, it isn't supported by Internet Explorer 6 (lot of them still used!), or do conditional use:
if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);
indexOf is probably coded in native code, so it is faster than anything you can do in JavaScript (except binary search/dichotomy if the array is appropriate).
Note: it is a question of taste, but I would do a return false; at the end of your routine, to return a true Boolean...
Here's some meta-knowledge for you - if you want to know what you can do with an Array, check the documentation - here's the Array page for Mozilla
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
There you'll see reference to indexOf, added in Javascript 1.6
A robust way to check if an object is an array in javascript is detailed here:
Here are two functions from the xa.js framework which I attach to a utils = {} ‘container’. These should help you properly detect arrays.
var utils = {};
/**
* utils.isArray
*
* Best guess if object is an array.
*/
utils.isArray = function(obj) {
// do an instanceof check first
if (obj instanceof Array) {
return true;
}
// then check for obvious falses
if (typeof obj !== 'object') {
return false;
}
if (utils.type(obj) === 'array') {
return true;
}
return false;
};
/**
* utils.type
*
* Attempt to ascertain actual object type.
*/
utils.type = function(obj) {
if (obj === null || typeof obj === 'undefined') {
return String (obj);
}
return Object.prototype.toString.call(obj)
.replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase();
};
If you then want to check if an object is in an array, I would also include this code:
/**
* Adding hasOwnProperty method if needed.
*/
if (typeof Object.prototype.hasOwnProperty !== 'function') {
Object.prototype.hasOwnProperty = function (prop) {
var type = utils.type(this);
type = type.charAt(0).toUpperCase() + type.substr(1);
return this[prop] !== undefined
&& this[prop] !== window[type].prototype[prop];
};
}
And finally this in_array function:
function in_array (needle, haystack, strict) {
var key;
if (strict) {
for (key in haystack) {
if (!haystack.hasOwnProperty[key]) continue;
if (haystack[key] === needle) {
return true;
}
}
} else {
for (key in haystack) {
if (!haystack.hasOwnProperty[key]) continue;
if (haystack[key] == needle) {
return true;
}
}
}
return false;
}