1

I've been seeing conflicting information on whether a custom controller is instantiated with a "new" keyword or simply applied to the $scope object.

The documentation site says,

Angular applies (in the sense of JavaScript's Function#apply) the controller constructor function to a new Angular scope object, which sets up an initial scope state. This means that Angular never creates instances of the controller type (by invoking the new operator on the controller constructor). Constructors are always applied to an existing scope object.

But it seems like in Angular 1.2, there is an "as" construct that will rename a controller to something else as in:

<body ng-controller="DemoController as demo">
    <tr ng-repeat="student in demo.students">
        <td>{{student.name}}</td>
    </tr>
</body>

function DemoController() {
    this.students = [...]
}

So this makes it seem like a controller is being instantiated using the new keyword.

Which one is it? Can someone clarify this?

Dan
  • 59,490
  • 13
  • 101
  • 110
platypus
  • 1,165
  • 5
  • 27
  • 47
  • I'm not terribly familiar with angular, but it _looks_ like `as` is just an alias. Why does `as` look to you like it has anything to do with `new`? – Matt Ball Jun 12 '13 at 02:57
  • Does this question have anything to do with angularjs-directive? – Ye Liu Jun 12 '13 at 03:00
  • because inside the definition of DemoController(), there is a "this.students = [...]" which means that demo is the object that refers to "this" which can happen if we do "demo = new DemoController()" – platypus Jun 12 '13 at 03:00
  • Where does your `DemoController as demo` example come from? Angular 1.2. is still quite far off (1.1.5 is still in the unstable branch) but I doubt they're going to be changing controllers to be instantiated with `new`, that would be a very big change. I would go with the 'Angular never creates instances of the controller' statement from the documentation. – Sly_cardinal Jun 12 '13 at 03:38
  • I just watched the "What's new in version 1.5" live on YouTube from the angularjs channel. – platypus Jun 12 '13 at 03:39

1 Answers1

2

The "as" syntax is only an alias and the documentation is correct that Angular never creates instances of the controller type by invoking the new operator on the controller constructor. The new behavior with aliasing is such that now $ControllerProvider does a regexp test for the presence of the as keyword and, if present, stores a reference to the controller on the local scope under the alias name.

Here is a link to the git feature commit that changed the relevant code.


Also: From the Angular source (1.1.5), here is the code in $ControllerProvider that creates the controller:

instance = $injector.instantiate(expression, locals);

and here is the instantiate method:

function instantiate(Type, locals) {
  var Constructor = function() {},
      instance, returnedValue;

  // Check if Type is annotated and use just the given function at n-1 as parameter
  // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
  Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
  instance = new Constructor();
  returnedValue = invoke(Type, instance, locals);

  return isObject(returnedValue) ? returnedValue : instance;
}

So you can see that the new keyword is indeed invoked but it's invoked on an empty generic function called Constructor, not the controller constructor. First the prototype of the empty constructor is set to the prototype of the Angular Type that is passed in to the injector.

Dan
  • 59,490
  • 13
  • 101
  • 110
  • But, for example, on the Angular API page for $resource, their example (script.js) contains the following code: BuzzController.prototype = { ... } This looks like the Controller will be used with the "new" keyword. http://docs.angularjs.org/api/ngResource.$resource – platypus Jun 12 '13 at 19:47
  • See my edit, perhaps it will make the issue a little clearer. – Dan Jun 13 '13 at 21:23