Search code examples
javascriptclassobjectprototype

Convert keys and prototype methods to camelcase


I have a class instance whose constructor takes an object or a JSON string representing that object. *

Because that JSON comes from a remote source, I like to ensure that the properties all have a lowercase first letter. However I've noticed that the method I'm using to do so (Object.keys()) ignores prototype methods. This makes sense after reading the documentation. I considered Object.getOwnPropertyNames() instead but given that I'm not dealing with enumerable vs non-enumerable (as far as I know), that wouldn't make a difference.

Is there an alternative method I can use to lowercase the first letter of all keys and prototype methods?

Thanks. Demonstration below.

class B {
  constructor() {
    this.MyProperty = "Hello world!";
  }
  MyMethod() {}
}

class A {
  constructor(b) {
    console.log(`MyMethod exists before lowercasing: ${!!b.MyMethod}`);
    b = Object.keys(b).reduce((copy,key) => ({...copy,  [`${key[0].toLowerCase()}${key.slice(1)}`]: b[key]}),{});

    console.log(`MyMethod exists after lowercasing: ${!!b.myMethod || !!b.MyMethod}`);
    console.log(`MyProperty has been lowercased: ${!!b.myProperty}`);
  }
}

let b = new B();
let a = new A(b);


* I've removed this for sake of brevity.


Solution

  • You could get the prototype from the instance using Object.getPrototypeOf(instance) and then invoke Object.getOwnPropertyNames() on the prototype to get the list of prototype methods.

    Using Array.prototype.reduce() you can combine the prototype methods as well as the keys of the object instance you have given into a single object and apply your lower-casing logic subsequently:

    class B {
      MyMethod() { return true }
    }
    
    class A {
      constructor(b) {
        console.log(`MyMethod exists before lowercasing: ${!!b.MyMethod}`);
        var proto = Object.getPrototypeOf(b);
        var comp = Object.getOwnPropertyNames(proto).reduce((obj, key) => {obj[key] = proto[key]; return obj}, {...b})
        b = Object.keys(comp).reduce((copy,key) => ({...copy,  [`${key[0].toLowerCase()}${key.slice(1)}`]: b[key]}),[]);
         
        console.log(`MyMethod exists after lowercasing: ${!!b.myMethod || !!b.MyMethod}`);
      }
    }
    
    let b = new B();
    let a = new A(b);