2

I am using:

var ReportsServiceCall = function () { };

ReportsServiceCall.prototype = new ServiceCall();

With this code, is the ServiceCall a fresh instance each time a new ReportsServiceCall is created? I need it to be so.

Evan Davis
  • 35,493
  • 6
  • 50
  • 57
williamsandonz
  • 15,864
  • 23
  • 100
  • 186
  • I think he's asking whether it's a new instance of ServiceCall on each new ReportsServiceCall. – regulus Dec 02 '13 at 22:31
  • Yes, I'm after what regulus described. – williamsandonz Dec 02 '13 at 22:34
  • Your parent's instance variables are now put on the prototype of the Child and it's not a good way to have to create an instance of Parent to set 50% of the inheritance of Child. More on prototype here: http://stackoverflow.com/a/16063711/1641941 – HMR Dec 02 '13 at 23:35

5 Answers5

3

Nope

As you have it written, the prototype is only setup once. However, that's not a very good way to write it.

I would write it like this

var ReportsServiceCall = function () {

  // parent constructor; optional
  ServiceCall.call(this);
};

// setup prototype; see comment below
ReportsServiceCall.prototype = Object.create(ServiceCall.prototype, {
  constructor: {
    value: ReportsServiceCall,
    enumerable: false,
    writable: true,
    configurable: true
  }
});

Note: Aside from setting super_, this is how node.js is doing vanilla inheritance in their util.inherits function.

This is very effective technique once you understand how it works.

maček
  • 76,434
  • 37
  • 167
  • 198
  • 3
    I agree with using Object.create for prototype part and +1 for re using ServiceCall constructor. The second parameter of Object.create cannot be used in older browsers even if you shim it. For the older browsers it's saver to do: `ReportsServiceCall.prototype = Object.create(ServiceCall.prototype);ReportsServiceCall.prototype.constructor = ReportsServiceCall;` – HMR Dec 02 '13 at 23:38
  • Thanks guys, looks like I'm going to drop support for ie8 then and go with this. (oh how I've waited for this day) – williamsandonz Dec 06 '13 at 02:39
2

With this code, is the ServiceCall a fresh instance each time?

No and it's not a good way to setup inheritance. At the moment you are calling new ServiceCall, you actually don't want to create an instance of ServiceCall (which arguments would you pass if the constructor requires parameters?). All you really want is add ServiceCall's prototype to ReportsServiceCall's prototype chain.

You should use Object.create instead and call the superclass constructor inside the child class constructor:

var ReportsServiceCall = function () {
    ServiceCall.call(this);
};

ReportsServiceCall.prototype = Object.create(ServiceCall.prototype);

See Benefits of using `Object.create` for inheritance for an extended explanation of this pattern.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • +1 As javascript accepts variadic arguments, maybe to use `apply` .. ? – Ken Kin Dec 02 '13 at 23:04
  • @KenKin, it's unlikely the parent constructor would take the exact same arguments sent to the child. – maček Dec 02 '13 at 23:06
  • @FelixKling, you might want to consider passing `{constructor: {value: ReportsServiceCall}}` to `Object.create`. Otherwise you end up with `(new ReportServiceCall).constructor.name; // ""` – maček Dec 02 '13 at 23:08
  • @maček: Hmm .. the inconsistency of the parameters order might be a controversial design problem .. – Ken Kin Dec 02 '13 at 23:14
  • @KenKin, in some cases you might have the same parameters; It's not a "design problem" to make the child constructor accept different arguments... – maček Dec 02 '13 at 23:19
  • @maček: Okay, so let me reword *problem* to *decision*. – Ken Kin Dec 02 '13 at 23:22
  • 1
    @maček Because JavaScript doesn't have named arguments as (for example) python I usually pass a args object. This object can be passed along through the function chain that make up a certain process and each function reads and sets whatever it needs. You can't do `someFunction(spacing=15, step=2);` but you can do `someFunction({spacing:15,step:2});`. This is particularly handy when you use mediator pattern and not sure in a certain function what the next function will be. – HMR Dec 03 '13 at 00:01
1

IMHO not, as you are setting the prototype just once

ladar
  • 5,858
  • 3
  • 26
  • 38
1

The prototype is only a single object that will be shared by all of the instances of ReportsServiceCall. If you need the ServiceCall constructor to be called for each ReportsServiceCall instance, you can do this:

function ReportsServiceCall() {
  ServiceCall.call(this);
};
ReportsServiceCall.prototype = new ServiceCall();
ReportsServiceCall.prototype.constructor = ReportsServiceCall;
sbking
  • 7,630
  • 24
  • 33
1

Not really.

A ReportsServiceCall is a ServiceCall, but create a ReportsServiceCall with new doesn't make it have its own properties which assigned in the constructor of ServiceCall.

Look at the following example:

var ServiceCall=function () {
    this.Id=Math.random();
};

var ReportsServiceCall=function () {
};

ReportsServiceCall.prototype=new ServiceCall();

var x=new ReportsServiceCall();
var y=new ReportsServiceCall();

alert(x.Id===y.Id); // true .. so, what Id for?

One of the solutions is:

var ReportsServiceCall=function () {
    ServiceCall.apply(this, arguments);
};
Ken Kin
  • 4,503
  • 3
  • 38
  • 76
  • `ServiceCall.apply(this, arguments)` is not ideal. It's unlikely the parent constructor would take the same arguments sent to the child. Probably better to provide the minimum solution. – maček Dec 02 '13 at 23:06