Constructor Functions and Controllers in AngularJS

Wednesday, November 12, 2014

AngularJSThere are a few points in “AngularJS: The Bad Parts” I’d be happy to debate, but let’s focus on “Bad Idea #4”, talking about controller constructor functions:

That’s right, these constructors never create new instances. They are “applied” to a scope object.

Let’s use the following example. A simple controller that is setup to use controller as syntax from the view.

var module = angular.module("app", []);

var MainController = function() {
      
    this.message = "Hello";
    
    this.changeMessage = function() {
        this.message = "Bonjour!";
    };

    this.isMainController = function(object) {
        return object instanceof MainController;
    };

    this.isObject = function(object) {
        return object instanceof Object;
    };

};

module.controller("MainController", MainController);

If we place the following markup in a view:

<div>
    {{ main.isMainController(main) }}
    {{ main.isObject(main) }}
</div>

.. we’ll see the output true and true. The first true is a good indication that Angular does use the controller function as a constructor function, in other words, Angular invokes the function using the new keyword. In fact, we can even rewrite a controller using the everyday constructor function and prototype object approach of JavaScript, and everything just works.

var MainController = function() {
    this.message = "Hello";         
};

MainController.prototype = {
       
   changeMessage: function() {
       this.message = "Bonjour!";
   },

   isMainController: function(object) {
       return object instanceof MainController;
   },

   isObject: function(object) {
       return object instanceof Object;
   }

};

The above is actually a good example of why I like working with Angular. You can write plain, simple JavaScript objects using established conventions and terminology, then plug the objects into Angular to achieve a goal. There is no magic required or intrusions from the framework. You can even start writing controllers using ES 6 class syntax, but that’s a topic for a future post.


Comments
gravatar Anna Thursday, November 13, 2014
I woud like to see the es6 post! There already is a es6 shim library :).
Thursday, November 13, 2014
Scott, do you mean there is no truth in the blogger's claim ? maybe he talked about $scope augmenting () ? As far as i remember, you yourself talked in a previous post about disadvantages of the "controller as" notation.
gravatar Lars Eidnes Thursday, November 13, 2014
Hi, Thanks for the feedback. The key sentence is this "This is what the page on Controllers *used* to say", emphasis mine. This is from the documentation for the pre-1.0 Angular, where these functions were indeed called without new. The point isn't that its good or bad to call it with new, but that the behaviour is documented with self-contradicting language.
gravatar Vitaly Brusentsev Friday, November 14, 2014
Scott, Thanks for bringing this topic up. I've been wondering, however, why the directive registration does not follow this approach. When you register a directive, the function passed will be called without new keyword. Is there some justification for this behaviour?
gravatar Scott Monday, November 17, 2014
@Vitaly - The function you register with .directive is only invoked once to create the directive definition. It is the link function that is invoked once instance. I guess they chose a different pattern for directives since "new" might imply a component that creates itself from scratch. The link function feels right since there are DOM elements being joined with bits of JavaScript code.
Comments are closed.

My Pluralsight Courses

K.Scott Allen OdeToCode by K. Scott Allen
What JavaScript Developers Should Know About ECMAScript 2015
The Podcast!