0

I have two files: BaseController.js and EventRecordController.js. EventRecord needs to inherit a few methods from BaseController.

BaseController

var Q = require('q'),
    util = require('../util');

exports.BaseController = function(req, res) {
    this.req = res;
    this.res = res;
    this.fields = {};
    this.error = {
        code: 200,
        message: 'BAD REQUEST: The parameters provided were invalid. See response body for error messages.',
        specific_message: ''
    };
};

// Utility method to handle returning errors that are thrown.
exports.BaseController.prototype.handle_errors = function(error) {
    if(this.error.code === 500) {
        util.internal_error(this.res, this.response_type);
    } else {
        var response = util.build_error_response(this.response_type, this.error.code, this.error.message, this.error.specific_message);
        util.send_response(this.res, this.response_type, this.error.code, response);
    }
};

// Check to see if a user is authenticated and whether they are using a correct response type.
exports.BaseController.prototype.validate_response_type_and_authenticate = function() {
    var deferred = Q.defer();
    util.validate_response_type_and_authenticate(this.req, this.res, function(auth_data, response_type) {

        this.auth_data = auth_data;
        this.company_user_uid = this.auth_data.data.company.uid;
        this.response_type = response_type;
        this.v3_token = this.auth_data.data.token;

        deferred.resolve();
    });
    return deferred.promise;
};

EventRecordController

var base_controller = require("./BaseController"),
    Q = require('q'),
    util = require('../util'),
    validator = require('validator');


exports.EventRecordController = function(req, res) {

    function EventRecord(req, res) {
        base_controller.BaseController.apply(this, arguments);
    }

    // Inherit from BaseController, then fix constructor.
    EventRecord.prototype = new base_controller.BaseController();
    EventRecord.prototype.constructor = EventRecord;

    EventRecord.run = function() {
        console.log(this.error);
    };

    return EventRecord;
};

When I run the following code, this.error logs as undefined from within the run() method.

var event_record_controller = require("./controllers/EventRecordController"),
    util = require('./util'),
    validator = require('validator');

exports.record = function(req, res) {
    var controller = new event_record_controller.EventRecordController(req, res);
    controller.run();
};

I think I'm missing something obvious here, but my experience with prototype based inheritance is limited.

6
  • 1
    If a constructor returns an object, the object created by new will be discarded. So, new EventRecordController() is returning the function EventRecord rather than an instance. Commented Mar 12, 2014 at 12:53
  • Did you want to use revealing module pattern for the EventRecordController? Then you're missing the IEFE call Commented Mar 12, 2014 at 12:59
  • Why is run not a function on the EventRecord prototype, but a "static" one? Commented Mar 12, 2014 at 13:00
  • You've got issues with nested objects because you're doing the inheritance wrong Commented Mar 12, 2014 at 13:01
  • 1
    The callback to util.validate_response_type_and_authenticate is probably called with the wrong this either Commented Mar 12, 2014 at 13:01

1 Answer 1

1

this.error is undefined because run is being called directly on the constructor, which doesn't have an error, rather than one of its instances.

Methods that are attached directly to the constructor aren't inherited. For that, they should be attached to the prototype:

// "static" method available only through the constructor itself
EventRecord.run = function() {
    console.log(this.error);
};

// "class" method inherited by instances of `EventRecord`
EventRecord.prototype.run = function () {
    console.log(this.error);
};

But, you also don't yet have an instance of EventRecord to call .run() on.

When a constructor returns an object, the instance that was created by using new will be discarded. So, calling new EventRecordController() is just returning the function EventRecord.

var controller = new event_record_controller.EventRecordController(req, res);
console.log(typeof controller);     // function
console.log(controller.name);       // "EventRecord"

controller = new controller(req, res);
console.log(typeof controller);     // object

You could revise EventRecordController to return an instance of EventRecord:

// ...

return new EventRecord(req, res);

Though, you might consider consolidating the 2 constructors rather than having one generate the other:

exports.EventRecordController = function(req, res) {
    base_controller.BaseController.apply(this, arguments);
};

util.inherits(exports.EventRecordController, base_controller.BaseController);

exports.EventRecordController.prototype.run = function () {
    console.log(this.error);
};
Sign up to request clarification or add additional context in comments.

1 Comment

This fixed my issue, and gave me a better understanding of how to use prototypal inheritance. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.