3

ive got an object:

var car = {
    company: "Honda",
    year: "2011",
    Model: "Brio"
}

I was wondering if there exists an inherited method (is that the right phrase?) to check if a value exists inside a given object, somewhat like x.hasOwnProperty, or if (x in car). Or, should I write my own.

I've done a few google searches, but they all either lead to hasOwnProperty or to check if a value exists inside an array.

Editing to please all the people in the comments: There are two use cases i could think of where this would be useful:

  1. checking for undefined keys and reporting which one

    if (!car.isInvalid(car, undefined)) 
        validCarsArray.push (car);
    
  2. Checking if a general user input exists in an object

    var text = searchBox.input; 
    
    validCarArrays.forEach (function (car) {
        if (car.hasOwnValue(car, text)) {
        displayToUserAsResult (car);
        }
    });
    
Daedalus
  • 195
  • 1
  • 3
  • 15
  • So, iterate over values and check if one equals to it. – zerkms Jan 30 '16 at 08:51
  • @zerkms yes. I was just wondering if there was already an existing method – Daedalus Jan 30 '16 at 08:52
  • What do you mean by value here? – thefourtheye Jan 30 '16 at 08:53
  • @thefourtheye there is a key, and a value. `company` is a key, `"Honda"` is a value – Daedalus Jan 30 '16 at 08:54
  • 1
    @CakeToppings Considering, that the value of a property could be a primitive, another object or a function, a method checking for a value wouldn't be very useful. – Teemu Jan 30 '16 at 08:54
  • can you explain what you mean _a value exists inside a given object_? you want avoid some values like _null_ and _undefined_ or what? – Grundy Jan 30 '16 at 08:58
  • @Grundy avoiding _null_ or _undefined_ is what i had in mind. In the object im creating there are a lot of keys, so checking validating each one would make the code very unpleasing to the eye and comprehensible, im willing to sacrifice some efficiency to make it a lot more readable – Daedalus Jan 30 '16 at 09:02
  • in this case you can just check values like `if(car[x] != null)` – Grundy Jan 30 '16 at 09:04
  • 1
    @CakeToppings your last comment has made your question very different then what it asks currently. What you want is to search through an array of cars (or just an object and checking its keys), and checking if there is no `null` or `undefined` or even `''` (empty string) value – KarelG Jan 30 '16 at 09:05
  • @Grundy however that is for a specific key, if got around 14, i dont want to have a 6 long if statement checking each one if it contains a null or undefined. Unless im missing something – Daedalus Jan 30 '16 at 09:05
  • @KarelG Not sure how checking for undefined is not considered checking for a value. – Daedalus Jan 30 '16 at 09:06
  • It's a matter of semantics. "_if a value exists_ " can be interpret as if a given object has a key which holds the given value. What you're looking for is checking for invalid values. That means that for each key, the value shouldn't be null/undefined/empty string – KarelG Jan 30 '16 at 09:09
  • 2
    can you provide sample input and expected output what you want? – Grundy Jan 30 '16 at 09:10
  • @Grundy Sure, ill even add a user case. There is a search box, a user can type in whatever he wants, 2011, honda or brio. Because i dont know if he meant the year, company or model, i can simply check if a value exists inside the object. lets say the `var text = searchBox.input; if (o.hasOwnValue(text)) { return o }` the function hasOwnValue should return true, or maybe the key, doesnt really matter – Daedalus Jan 30 '16 at 09:18
  • @CakeToppings, add sample to your question instead comment – Grundy Jan 30 '16 at 09:20
  • @Grundy added, along with another use case im currently using the result for. – Daedalus Jan 30 '16 at 09:53
  • The proper etiquette here is that you do NOT add a final answer to your question. Questions are questions and should stay as the question. Answers are answers and the selected/best answer is indicated by the green checkmark. The two should not be combined. – jfriend00 Jan 30 '16 at 10:06
  • @jfriend00 pardon, i was not aware of that, fixed. – Daedalus Jan 30 '16 at 10:10

5 Answers5

14

Let's say we start with

const obj = {foo : "bar"};

Check for a value:

const hasValue = Object.values(obj).includes("bar");

Check for a property:

// NOTE: Requires obj.toString() if key is a number
const hasProperty = Object.keys(obj).includes("foo");

Multi-level value:

function hasValueDeep(json, findValue) {
    const values = Object.values(json);
    let hasValue = values.includes(findValue);
    values.forEach(function(value) {
        if (typeof value === "object") {
            hasValue = hasValue || hasValueDeep(value, findValue);
        }
    })
    return hasValue;
}

Multi-level property:

function hasPropertyDeep(json, findProperty) {
    const keys = Object.keys(json);
    let hasProperty = keys.includes((findProperty).toString());
    keys.forEach(function(key) {
        const value = json[key];
        if (typeof value === "object") {
            hasProperty = hasProperty || hasPropertyDeep(value, findProperty);
        }
    })
    return hasProperty;
}
Gibolt
  • 42,564
  • 15
  • 187
  • 127
4

No, there is no built in method to search for a value on an object.

The only way to do so is to iterate over all the keys of the object and check each value. Using techniques that would work even in old browsers, you can do this:

function findValue(o, value) {
    for (var prop in o) {
        if (o.hasOwnProperty(prop) && o[prop] === value) {
            return prop;
        }
    }
    return null;
}

findValue(car, "2011");    // will return "year"
findValue(car, "2012");    // will return null

Note: This will return the first property that contains the search value even though there could be more than one property that matched. At the cost of efficiency, you could return an array of all properties that contain the desired value.

Note: This uses the extra .hasOwnProperty() check as a safeguard against any code that adds enumerable properties to Object.prototype. If there is no such code and you're sure there never will be, then the .hasOwnProperty() check can be eliminated.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • The OP asked about the value. – gnerkus Jan 30 '16 at 08:57
  • I might be missing something, but if you iterate over the object keys, why are you checking if the object has that key with `hasOwnProperty`? – Daedalus Jan 30 '16 at 09:09
  • @CakeToppings - Because you're looking for only "own" properties, but `for/in` gives you all properties including inherited properties. You typically don't want properties from the base object such as "hasOwnProperty" itself to be searched, but rather only search the properties that your own code added to the object. You can remove that extra check if you want, but usually you want to exclude inherited properties from a search like this. – jfriend00 Jan 30 '16 at 09:11
  • @jfriend00 i might be mistaken, but doesnt `hasOwnValue` not search over inheritance? [https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty](_Direct versus inherited properties_) it returns false for `hasOwnProperty` – Daedalus Jan 30 '16 at 09:14
  • @CakeToppings - Your last comment seems to have some typos and be missing some things (for one the link you included does not work) and you refer to `hasOwnValue` which I don't know what that is. – jfriend00 Jan 30 '16 at 09:16
  • `for/in` lists any enumerable properties (both "own" properties and "inherited" properties). By default an empty object does not have any enumerable properties, but some libraries add new methods to the `Object.prototypte` and if they don't do it properly some of those can be enumerable. This has happened many times. For that reason, it is safer to use `.hasOwnProperty()`. `Object.keys()` returns only own properties so it is safe in this regard if you are OK with the browser support that it requires. – jfriend00 Jan 30 '16 at 09:19
  • @CakeToppings - I added a note about the `.hasOwnProperty()` check to the end of my answer. It is there for defensive coding reasons. – jfriend00 Jan 30 '16 at 09:23
  • @jfriend00 thank you! works wonderfully. I usually tend to avoid stackexchange, since it is so _toxic in a nice kinda way_, where people just jump on you like a flock of birds if you make a simple mistake, instead of explaining what you did wrong. Still dont know why i got downvoted. Regardless, everyone should explain just like you did, great job! – Daedalus Jan 30 '16 at 09:30
  • @CakeToppings - The best way to avoid downvotes is to write a very clear question that is on-topic for the site. And, monitor comments over the next 30 minutes or so and if anyone asks any question indicating some confusion, then immediately edit your question to make sure it is completely clear. The site is not tolerant of unclear questions from people who don't immediately work to clarify their question. I was confused about what your question meant (I originally wrote an answer to something different than what you intended to ask) so a downvote does not surprise me. – jfriend00 Jan 30 '16 at 09:34
  • @jfriend00 can you tell me what was unclear? I got this feedback from other people, and Im honestly searching for what is unclear in searching if a certain value exists in a certain object – Daedalus Jan 30 '16 at 09:51
  • @CakeToppings - Your references to `x.hasOwnProperty, or if (x in car)` confused me to think that you were looking for a property even though your question mentioned a value. It left me unsure what you meant. Showing the type of function you wanted (e.g. what the function arguments would be), what it's inputs would be and what it's output would be for various inputs would have been completely unambiguous. Several people asked you for sample input and output which you did not provide. Then your comments about "avoiding `null` or `undefined` confused me even further. – jfriend00 Jan 30 '16 at 10:10
1

This function uses Object.keys() and returns an array with the keys for the object which has the given value.

The Object.keys() method returns an array of a given object's own enumerable properties, in the same order as that provided by a for ... in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).

var car = {
    company: "Honda",
    year: "2011",
    Model: "Brio"
};

function getKeysWithValue(v, o) {
    return Object.keys(o).filter(function (k) {
        return o[k] === v;
    });
}

document.write('<pre>' + JSON.stringify(getKeysWithValue('Honda', car), 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

There is no built-in function but it can be done using Object.keys() and [].some():

function hasValue(obj, value) {
  return Object.keys(obj).some((key) => obj[key] == value);
}

var car = {
  company: "Honda",
  year: "2011",
  Model: "Brio"
}

snippet.log('car has Honda: ' + hasValue(car, 'Honda'));
snippet.log('car has NotHonda: ' + hasValue(car, 'NotHonda'));
<script src="https://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Shanoor
  • 13,344
  • 2
  • 29
  • 40
0

I used this function, to check wether or not array2 contains a common value with array1.

const array1 = ['a','b','c','x'];
const array2 = ['z','y','x'];


function ContainsCommonItem3(arr1, arr2){
        return arr1.some(item => arr2.includes(item));
    }
Noohone
  • 694
  • 5
  • 12