skip to Main Content

How do I check if a variable contains a certain property?

Let’s assume:

var x = 'some string';

Then I would like to do:

if ('trim' in x)

but that gives me a:

Uncaught TypeError: Cannot use 'in' operator to search for 'trim' in string

I can make it work by using:

'trim' in x.__proto__

but according to MDN __proto__ is deprecated and its use is (quote) "controversial and discouraged".

How can I achieve this then?

I have tried to use Object.keys(x) but that only lists the keys that are valid as indexes, not the properties.

I know that, in this specific example, I could simply use typeof x === 'string' but that’s not a universal solution.

3

Answers


  1. You can verify if any variable has a property like the function hasProperty in the snippet below.

    function hasProperty ( mySubject, myProperty )
    {
      if ( ! ((mySubject === null) || (mySubject === undefined)) )
      {
        if ( mySubject instanceof Object )
        {
          return Reflect.has(mySubject, myProperty);
        }
        
        else if ( typeof mySubject[myProperty] != 'undefined' )
        {
          return true;
        }
      }
      
      return false;
    }
    
    // TESTING //
    
    const mySubject1 = 'Anything goes here';
    const mySubject2 = 300;
    const mySubject3 = new Object;
    const mySubject4 = undefined;
    const mySubject5 = { valueOf: undefined };
    
    console.log('Is mySubject1.valueOf defined?', hasProperty(mySubject1, 'valueOf'));
    // Outputs: Is mySubject1.valueOf defined? true
    
    console.log('Is mySubject2.valueOf defined?', hasProperty(mySubject2, 'valueOf'));
    // Outputs: Is mySubject2.valueOf defined? true
    
    console.log('Is mySubject3.valueOf defined?', hasProperty(mySubject3, 'valueOf'));
    // Outputs: Is mySubject3.valueOf defined? true
    
    console.log('Is mySubject4.valueOf defined?', hasProperty(mySubject4, 'valueOf'));
    // Outputs: Is mySubject3.valueOf defined? false
    
    console.log('Is mySubject5.valueOf defined?', hasProperty(mySubject5, 'valueOf'));
    // Outputs: Is mySubject5.valueOf defined? true

    Note that you can use Reflect.has(obj, prop). But if obj do not pass obj instanceof Object then an exception will be thrown, which is what happens when using mySubject1, mySubject2 or mySubject4 as the obj parameter.

    Login or Signup to reply.
  2. If for some reason you want to avoid directly accessing the property via x[prop], you could first pass the value to the Object function before testing with in.

    let x = 'some string';
    console.log(x != null && 'trim' in Object(x));
    Login or Signup to reply.
  3. The in operator does not work with primitive values. There is also Reflect.has() which does the same as in but it also has the same limitation.

    However, a simple way to go around it is to pass the values through the Object constructor without using new. Doing that will convert primitives to their wrapper classes while if the input is an object, it gets returned as-is. So, Object("a string") is the same as new String("a string") but Object({ some: "object" }) is the same as { some: "object" }. And this will allow lookups via in (or Reflect.has()) on those values.

    One caveat is that Object(null) or Object(undefined) will create a plain object. Which will potentially return a false positive for something like "toString in Object(null). Since those two values cannot have properties, they can be excluded from the check with

    target != null && prop in Object(target)
    

    Demo:

    const prop = "trim";
    
    function propIn(target, prop) {
      return target != null && prop in Object(target);
    }
    
    const string = "a string";
    const number = 42;
    const bigint = 42n;
    const boolean = true;
    const symbol = Symbol("a symbol");
    const obj = {an: "object"};
    const objWithProp = {trim() { return "object with a .trim() method"; } }
    
    console.log( propIn(string     , prop));
    console.log( propIn(number     , prop));
    console.log( propIn(bigint     , prop));
    console.log( propIn(boolean    , prop));
    console.log( propIn(symbol     , prop));
    console.log( propIn(null       , prop));
    console.log( propIn(undefined  , prop));
    console.log( propIn(obj        , prop));
    console.log( propIn(objWithProp, prop));
    .as-console-wrapper { max-height: 100% !important; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search