4

Extending prototypical classes in node.js or javascript in general. (js newb)

I was looking at the source-code of expressjs and saw this:

var mixin = require('utils-merge'); 
....
mixin(app, proto);
mixin(app, EventEmitter.prototype);

Utils-merge seems like an external module. What are the difference of above and just doing something like:

var util = require('util');
....
util.inherit(app, proto);
util.inherit(app, EventEmitter);

And is this still trying to extend properties? I'm kind-a lost here:

app.request = { __proto__: req, app: app }; // what is the equivalent for this in util?
app.response = { __proto__: res, app: app };

If so, will that still work even if util.inherit is used?

app.request = util.inherit(app, req)

Or something like that? jshint says __proto__ is depricated.


Additionally I also saw this?

var res = module.exports = {
  __proto__: http.ServerResponse.prototype
};

Could this be?

var res = module.exports = util.inherits...??
majidarif
  • 18,694
  • 16
  • 88
  • 133

2 Answers2

6

I was looking at the source-code of expressjs

You might also want to have a look at this question about how app is supposed to work.

What are the differences between utils-merge as above and just doing something like:

var util = require('util');
....
util.inherit(app, proto);
util.inherit(app, EventEmitter);

They're doing totally different things:

utils-merge
Merges the properties from a source object into a destination object.

util.inherits

Inherit the prototype methods from one constructor into another. The prototype of constructor will be set to a new object created from superConstructor.

Also read their sources!

app (while being a function for odd reasons) is not a constructor, but is supposed to be a (plain) object - an instance made by createApplication. So there's no way to do "class inheritance" here. And you cannot use utils.inherits multiple times on the same constructor anyways, as it does overwrite the .prototype property of it.

Instead, that mixin function will simply copy all the properties from proto and then all properties from EventEmitter.prototype to the app object.

And is this still trying to extend properties? I'm kind-a lost here:

app.request = { __proto__: req, app: app }; // what is the equivalent for this in util?
app.response = { __proto__: res, app: app };

Use the native Object.create function for this:

app.request = Object.create(req);
app.request.app = app;
app.response = Object.create(res);
app.response.app = app;

If so, will that still work even if util.inherit is used?

app.request = util.inherit(app, req) // Or something like that?

No, really not.

jshint says __proto__ is depricated.

Yes, you should use Object.create instead. But the nonstandard __proto__ will probably be kept for compatibility.

Additionally I also saw this?

var res = module.exports = {
  __proto__: http.ServerResponse.prototype
};

Could this be?

var res = module.exports = util.inherits...??

No, again that's a case for Object.create:

var res = module.exports = Object.create(http.ServerResponse.prototype);
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • One more question, how about this? `this.request.__proto__ = parent.request;` – majidarif Jul 19 '14 at 14:32
  • 1
    What is `parent`? How was `this.request` initially created? But no, [you should really not change the `__proto__`](http://stackoverflow.com/a/23809148/1048572) after an object was created. – Bergi Jul 19 '14 at 16:41
  • It's on the expressjs application code. I dont really understand all the inheritance all over the code. – majidarif Jul 21 '14 at 15:35
  • Ah, you mean [this file](https://github.com/visionmedia/express/blob/master/lib/application.js). Yes, they're really doing ugly things there, apparently with the aim to extend the native object without modifying them. But, why do you *need* to understand all the code? Just use the library. – Bergi Jul 21 '14 at 18:39
  • because [this](http://stackoverflow.com/questions/24869267/understanding-expressjs-base-code). Technically trying to create a simple similar one for the net/tcp protocol. Instead of http. – majidarif Jul 22 '14 at 02:18
2

You can use ES6 in Node.js.

class myClass() {
  this.hi = function(){"hello"};

}

class myChild extends myClass() {

}

var c = new myChild(); c.hi(); //hello
Sara Fuerst
  • 5,688
  • 8
  • 43
  • 86
Code Whisperer
  • 22,959
  • 20
  • 67
  • 85
  • Though this would require the `--harmony` right? Also I'm still confused if I would rewrite their code to newer specs, how it would look. I believe __proto__ wouldnt be there anymore because node.js has util.inherit now. But i cant understand how to write it with util. – majidarif Jul 17 '14 at 17:46
  • If at all, the `class` keyword would need to be lowercased. I also fail to see how this answers the question. – Bergi Jul 17 '14 at 18:14
  • also classes are not implemented in v8 yet – vkurchatkin Jul 17 '14 at 21:45
  • But you can shim theme with Traceur no? – Code Whisperer Jul 18 '14 at 13:28