0

I'm trying to accomplish a function that receives an object as parameter and returns a class (or a constructor) generated based on the descriptive object received. Is there any resolvent without using 'eval'?

// this is the function to create class.
function createClass (option) {
    // TODO how to generate...
    // return classGenerated
}

// then, i can do this to create a 'Node' class.
createClass({
    name: "Node",
    data: {
        x: 0,
        y: 0
    },
    methods: {
        translate (dx, dy) {
            this.x += dx;
            this.y += dy;
        }
    }
})

// then i can create a instance by doing this below.
const node = new Node();

I've accomplished one version by 'eval' function. I want to know if there is any other better ways to do this. Thanks for you help.

BaoYukun
  • 13
  • 2

2 Answers2

1

Instead of standalone, dynamic variable names, consider using an object of classes instead, indexed by the class names (like Node) so that you can do something like const node = new createdClasses.Node():

const createdClasses = {};
function createClass ({ name, data, methods }) {
  class theClass {
    constructor() {
      Object.assign(this, data);
    }
  }
  Object.assign(theClass.prototype, methods);
  createdClasses[name] = theClass;
}
createClass({
  name: "Node",
  data: {
      x: 0,
      y: 0
  },
  methods: {
      translate (dx, dy) {
          this.x += dx;
          this.y += dy;
      }
  }
})

const node = new createdClasses.Node();
node.translate(5, 5);
console.log(node.x);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • BTW unlike created in form of 'class Node {...}', when we logged it in browser's console panel, the result logged out 'theClass {x:5, y:5 }'. Is there any other way to make it log 'Node {x:5, y: 5}' – BaoYukun Jan 13 '19 at 02:02
  • I can't figure out a way to use dynamic class names. You can check out https://stackoverflow.com/questions/5871040/how-to-dynamically-set-a-function-object-name-in-javascript-as-it-is-displayed-i , I tried a few variations but couldn't get the `console.log` to display the passed `name` variable – CertainPerformance Jan 13 '19 at 02:45
0

You can take advantage of Javascript clojures, but you have to have a slightly different behavior: you cannot define a class globally (AFAIK), but you can return one.

So, the usage will become:

const Node = createClass(...)
const node = new Node();

To get this result, the createClass method should return a new class definition:

function createClass(options) {
  return class {
    constructor() {
      Object.assign(this, options.data, options.methods)
    }
  }
}

Now you can do something like:

const node = new Node();

node.translate(10, 15)
console.log(node.x)    // 10

node.translate(13, 15)
console.log(node.x)    // 23

BTW, in ES6 the createClass method can become really wonderful in my opinion :)

const createClass = ({ data, methods }) =>
  class {
    constructor() {
      Object.assign(this, data, methods)
    }
  }
0xc14m1z
  • 3,675
  • 1
  • 14
  • 23