skip to Main Content

I need to find out the value of "name" inside on the obj object. How can I find it without function invocation?

I wanna use just obj.isActive not obj.isActive()

let obj = {
  name: "X Æ A-12 Musk",
  isActive: function () {
    return this.name.length > 4;
  },
};

// and after a while I need to check if is active:

console.log(obj);

// { 
//   name: 'X Æ A-12 Musk',
//   isActive: [Function: isActive]  <--------- NOT COOL ! 
// }


If use an IFEE:

let obj = {
  name: "X Æ A-12 Musk",
  isActive: (function () {
    return this.name.length > 4;
  })(),
};

I get:

return this.name.length > 4;
                ^
TypeError: Cannot read properties of undefined (reading 'length') 

4

Answers


  1. If you do not want to have to call isActive as a function, you can use a getter.

    const obj = {
      name: "X Æ A-12 Musk",
      get isActive () {
        return this.name.length > 4;
      },
    };
    
    console.log(obj.isActive);
    Login or Signup to reply.
  2. It’s not clear from your question why you can do an IIFE but not a getter, but here are some other potential workarounds.

    1. Use a Proxy to intercept the property accessor:

    If you can’t modify the object itself you could wrap it in a Proxy, and pass the proxy to the library.

    let obj = {
      name: "X Æ A-12 Musk",
      isActive: function () {
        return this.name.length > 4;
      },
    };
    
    const proxy = new Proxy(obj, {
      get(target, prop) {
        if (prop === 'isActive') {
          return target?.isActive?.();
        }
        return target[prop]
      }
    });
    
    console.log(proxy.isActive); // true
    console.log(proxy.name); // "X Æ A-12 Musk"
    console.log(proxy);
    /*
    {
      "name": "X Æ A-12 Musk",
      "isActive": true
    }
    */

    This could be generalized to invoke any getter function if it’s present on the target:

    let obj = {
      name: "X Æ A-12 Musk",
      isActive: function () {
        return this.name.length > 4;
      },
    };
    
    const proxy = new Proxy(obj, {
      get(target, prop) {
        const x = target[prop];
        return typeof x === 'function' ? target[prop]() : x;
      }
    });
    
    console.log(proxy.isActive); // true
    console.log(proxy.name); // "X Æ A-12 Musk"
    console.log(proxy);
    /*
    {
      "name": "X Æ A-12 Musk",
      "isActive": true
    }
    */

    Note: I’m invoking target[prop]() instead of x() here because invoking the disassociated function x() has scope implications that could produce errors or unexpected results.(The same issue that makes your IIFE blow up.)

    2. Use Object.defineProperty to establish the getter.

    Again, it’s not clear to me why you can’t put a getter on the object literal directly, so I don’t know if this is viable either.

    let obj = {
      name: "X Æ A-12 Musk",
      isActive: function() {
        return this.name.length > 4;
      },
    };
    
    Object.defineProperty(obj, "isActive", {
      get() {
        return this.name.length > 4
      }
    })
    
    console.log(obj);
    /*
    {
      "name": "X Æ A-12 Musk",
      "isActive": true
    }
    */
    Login or Signup to reply.
  3. Similarly to ray’s answer, what about something like this:

    let obj = {
        name: "test"
    };
    
    Object.defineProperty(obj, "isActive", {
        get: function() {
            return obj.name.length > 3;
        }
    });
    
    console.log(obj.isActive); // Output: true

    If it helps, and you were to use it constantly, you could create a helper function:

       
    function defineIsActive(object, condition) {
        
        Object.defineProperty(obj, "isActive", {
            get: function() {
                return condition
            }
        });
    }
    
    let obj = {
      name: 'test'
    }
    
    // And simply use it like so:
    defineIsActive(obj, obj.name.length > 3)
    
    console.log(obj.isActive)
    Login or Signup to reply.
  4. I cannot add more properties to that object

    You can create wrapper object prototyped by the original object, and define getter in the former.

    let obj = {
      name: "X Æ A-12 Musk",
      isActive: function () {
        return this.name.length > 4;
      },
    };
    
    function makeWrapper (obj) {
      let wrapper = Object.create(obj);
      Object.defineProperty(wrapper, 'isActive', {
        get () { return obj.isActive(); },
        enumerable: true
      });
      return wrapper;
    }
    
    let obj2 = makeWrapper(obj);
    console.log(obj2);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search