Gatothgaj
Gatothgaj

Reputation: 1701

Adding functions dynamically to function.prototype

I am a newbie to nodejs. I am writing a helper function to build JSON using a schema, I am trying to add functions (mostly setters) to set values. The following is a simple version of it.

function Task() {
  this.action = {};
  this.schedule = {};
}

function capitalize(str) {
  return `${str[0].toUpperCase()}${str.slice(1)}`;
}

const scheduleProps = [
'startAt',
'repeatEvery',
'endAt',
'count',
'interval'
];

Add methods to it dynamically

for(var i=0; i<scheduleProps.length; i++) {
  Object.defineProperty(Task.prototype, `set${capitalize(scheduleProps[i])}`, {
    enumerable: true,
    configurable: false,
    writable: true,
    value: (value) => {
      this.schedule[scheduleProps[i]] = value;
    }
  });
}

When I call the following way I expect obj.schedule.repeatEvery to contain value 10.

obj = new Task();
obj.setRepeatEvery(10);

Instead I get

TypeError: Cannot set property 'repeatEvery' of undefined

I even tried to set the functions like so

  Task.prototype[`set${capitalize(scheduleProps[i])}`] = (val) => {
    this.schedule[scheduleProps[i]] = val;
  }

In this case I get

TypeError: Cannot set property 'interval' of undefined
at Task.(anonymous function) [as setRepeatEvery]

How can I set methods to a function.prototype dynamically? Thanks a lot for your help

Upvotes: 2

Views: 349

Answers (1)

Jitendra Khatri
Jitendra Khatri

Reputation: 774

You were facing that issue mainly because of function assignment for "value" key.

You can find some changes there which is creating a closure and also changed the syntax of assigning a function at key of an object.

Closure is created to maintain the value of i for that particular iteration.

function Task() {
  this.action = {};
  this.schedule = {};
}

function capitalize(str) {
  return `${str[0].toUpperCase()}${str.slice(1)}`;
}

const scheduleProps = [
    'startAt',
    'repeatEvery',
    'endAt',
    'count',
    'interval'
];

for(var i=0; i<scheduleProps.length; i++) {
  Object.defineProperty(Task.prototype, `set${capitalize(scheduleProps[i])}`, {
    enumerable: true,
    configurable: false,
    writable: true,
    value: (function(i) { return function(value) { this.schedule[scheduleProps[i]] = value;} })(i)
  });
}

obj = new Task();
obj.setRepeatEvery(10);

Upvotes: 1

Related Questions