0

I am new to javascript and my question might be outrightly stupid. I am not able to get the correct reference for this.

I am trying to write a controller object in javascript. The idea here is to make this an interface object where anyone can inherit from its prototype and override the methods for their being.

I just want to expose one method "process()" to the object and this method will call all the remaining methods and attributes. I am trying to achieve this by making all the other methods and attributes private by using closures. this is the sample snippet of my code

var ViewController = function() {

    var _viewName = null;


  var loadView = function(viewName) {

    console.log("now loading view : "+viewName+ " ...");
  };

    return {
        process : function(viewName){
            _viewName = viewName;
            loadView(_viewName);
        }
    };

};


var vController = ViewController();
vController.process("alphaView");

Now this works perfectly fine. But if I want to override the methods PreProcess, loadView, initView and PostProcess using prototype, it doesn work. I tried overriding using the Object.create like

var vController2 = Object.create(ViewController, {

  LoadView : function(viewName) {
    //some custom implementation
  },
  //and so forth
});

And if I change my implementation to define the methods outside using prototypes also doesn't work. Like

 var ViewController = function() {

      var _viewName = null;

      return {
        process : function(viewName){
          _viewName = viewName;
          loadView(_viewName);
        }
      };

    };

    ViewController.prototype.loadView = function(viewName) {

        console.log("now loading view : "+viewName+ " ...");
    };

The gist of my issue being that I want (a) an interface object for a controller where the user can override the the one basic method (LoadView,) (b) All these members are private to the controller object and be accessible via the "Process()" method

Please advise!

EDIT: edited the code to make it simple.

5
  • Please reduce your code to a minimal (or at least shorter) example of what you're trying to do. Commented Mar 17, 2013 at 22:28
  • If you want to override methods from outside the implementation, then don't make them private, local functions. Instead, add them to the actual object prototype. It's unclear what problem you're really trying to solve by only having one actual method process(). That sounds like your skirting the normal javascript features. Commented Mar 17, 2013 at 22:30
  • what I want is that a developer can actually create an inherited object of ViewController and implement its own LoadView method. For eg. the application can have multiple controllers, say controller1, controller2 etc and each doesn a different operation on its LoadView. But the controller object , whenever or wherever instantiated can call only process() i.e. the only way of calling LoadView is via process(). I might have got it all wrong and thats why i needed the advise. Commented Mar 17, 2013 at 22:36
  • I think the main source of confusion here (after what jfriend00 has said) is that f you return an Object from a constructor invoked with new, it throws away the constructor's own instance in favour of the returned object, which doesn't (necessarily/by default) inherit the same prototype as the constructor would. You may find this answer helpful. Commented Mar 17, 2013 at 22:40
  • @curioussam - OK, now that I better understand what you're trying to do, I added another option to my answer. Commented Mar 17, 2013 at 22:46

1 Answer 1

1

Put the methods you want people to be able to override on the prototype so they are real methods and are called as real methods by process(). Then, once you create an object of this type, you can create new override defintions for any methods and process() will automatically call them instead of the originals. One way to do that is like this:

function ViewController() {
}

ViewController.prototype = {
    loadView: function(viewName) {
        console.log("now loading view : "+viewName+ " ...");
    },
    preProcess: function(viewName) {
        console.log("now Pre Processing view : "+viewName+ " ...");
    },
    // other methods here ...
    process: function(viewNmae) {
        this.viewName = viewName;
        console.log(_viewName);
        this.preProcess(_viewName);
        this.loadView(_viewName);
        this.initView(_viewName);
        this.postProcess(_viewName);
    }
}

var controller = new ViewController();
controller.loadView = function(viewName) {
    // override function for loadView
}
controller.process(viewName);

If, you really want to prohibit the calling of the override methods, then you would have give up using javascript's built-in prototype mechanism (because it's public and any method there can be called). So, you could use your own scheme and just add new public methods for setting the override functions. In your existing code, change this:

return {
    process : function(viewName){
        _viewName = viewName;
        loadView(_viewName);
    }
};

to this:

return {
    process : function(viewName){
        _viewName = viewName;
        loadView(_viewName);
    },
    setLoadViewFn: function(fn) {
        loadView = fn;
    }
    // add other override setting functions here
};


// create controller object
var controller = new ViewController();
// set override function for loadView
controller.setLoadViewFn(function(viewName) {
    // override function for loadView
});
controller.process(viewName);
Sign up to request clarification or add additional context in comments.

8 Comments

so looks like using closure here to make these members "private" is not a good option. This is a paradigme shift for me as I came from a classic OO language
It's not a good option if you want to use javascript's built-in object/prototype features. You could use your scheme, but you'd have to make public methods for setting the override functions and store those in your own private instance data. That's the only way I know of to allow setting of the methods, but no way to call them outside of process().
@curioussam - Now that you've better described what you're trying to do, I've added another option using your existing code privacy mechanisms.
this makes sense and I can see some abstraction and encapsulation here! This might work. Thanks :)
this approach doesnt seem to work as it gives back an error, "SyntaxError: Expected an identifier but found 'function' instead "
|

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.