0

Is there a equivalent getattr() function for Javascript? Or can I like code my own function? I don't really know where to go. Python Code:

method = getattr(self, method_name)
method()
  • 2
    Javascript doesn't need a function for that - Javascript indexing and dot notation are two syntaxes for the same operation, unlike Python. – user2357112 Apr 10 '21 at 10:55
  • but, unlike Python, Javascript does need a function to call the `method` afterwards. – georg Apr 10 '21 at 11:04
  • @georg: No, `thing[name]()` does the right thing already - particularly, it binds `this` correctly. You just have to make sure you don't do something like `method = thing[name]; method()`, which *will* lose `this`. – user2357112 Apr 10 '21 at 11:10

2 Answers2

4

Unlike Python, in Javascript there's no difference between object properties (accessed with a dot) and "items" (accessed with square brackets).

Therefore, in Javascript, you can use square brackets to access properties indirectly, that is

someObj.propName

and

someObj[expression that returns 'propName']

do the same thing, particularly,

someObj.foo === someObj['foo']

This is similar to what getattr does, but there are a few caveats to keep in mind:

First, unlike getattr, [] won't throw if the property doesn't exist. It just silently returns undefined

Second, there's no option to provide a default value, so you have to use a conditional if you want it

value = propName in someObj ? someObj[propName] : defaultValue

The third, and most important, applies when the property in question is a method. In python, myObject.someMethod or getattr(someObj, methodName) will return a bound function, which is aware of its own host object, or self. Therefore, you can call the returned value directly:

class MyClass:
    def __init__(self):
        self.thing = 'hey'

    def test(self):
        print(self.thing)

myObject = MyClass()
methodName = 'test'

method = getattr(myObject, methodName)

method()  # ok

In javascript, myObject.someMethod or someObj[methodName] will return an unbound function, which "has no idea" to which object it belongs. So if you store it in a variable and call it later on, that won't work:

class MyClass {
    constructor() {
        this.thing = 'hey'
    }
    test() {
        console.log(this.thing);
    }
}

myObject = new MyClass()
methodName = 'test'

method = myObject[methodName]

method() // NOT OK

You have to "rebind" the method explicitly to be able to call it:

boundMethod = method.bind(myObject)
boundMethod() // ok

Note that this only applies when you store the method in a variable (or pass as a parameter). When you call it right away, everything works as expected:

myObject[methodName]()  // ok

To put it all together, a vague analog of python's getattr might look like this in Javascript:

function getattr(obj, prop, defaultValue = null) {

    if (prop in obj) {
        let val = obj[prop];
        if (typeof val === 'function')
            return val.bind(obj);
        return val;
    }

    if (arguments.length > 2) {
        return defaultValue;
    }

    throw new TypeError(`"${obj}" object has no attribute "${prop}"`)
}
georg
  • 211,518
  • 52
  • 313
  • 390
0

JS don't need a function but you can code on your own to simulate the similar behaviour.

const obj = {
  name: "XYZ",
  experience: 10,
  organization: "GOOGLE"
}

function getattr( obj, prop, def ){
  return prop in obj ? obj[prop] : def;
}

const value = getattr( obj, "name" );
console.log( value );
DecPK
  • 24,537
  • 6
  • 26
  • 42
  • This does the wrong thing when a property is explicitly set to `null` or `undefined`. You should use `in` to check if the property exists. – user2357112 Apr 10 '21 at 11:03
  • `var getattr = ( obj, prop, def ) => prop in obj ? obj[prop] : def;` is maybe better – Giuppox Apr 10 '21 at 12:41