0

I followed a AngularJS tutorial on http://www.tutorialspoint.com/angularjs/angularjs_services.htm

The method passed to CalcService service got me confused. Is Angular using revealing prototype or a different one. I was confused because that inner function declared in this.square should be private and not visible outside the context of the object. How Angular is able to access square.

mainApp.service('CalcService', function(MathService){
            this.square = function(a) { 
            return MathService.multiply(a,a); 
         }
});
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
RoHaN
  • 1,356
  • 2
  • 11
  • 21

3 Answers3

2

An AngularJS service is a very distinct thing.

When it's initialized, it gets newed. Take this as an example:

function CalcService() {
  this.square = function() {
    // square some stuff
  };
}

// then in the controller, directive, or wherever,
// it gets initialized behind the scenes like this
new CalcService();

However, it gets initialized as singleton, meaning that there's only ever one reference to the object, even if the component where you register it attempts to re-initialize it (see my recent answer on singletons in AngularJS).

Not sure what you mean when you mention a "revealing prototype pattern", but the this , in the case of an AngularJS service, is simply implementing a non-prototypal method on a new, regular JavaScript object.

Keeping with the same example above, in "normal" JavaScript, you could call new CalcService().square(). JavaScript doesn't have any native notion of private methods (though there are ways of implementing "class" methods that appear to be private.)

var service = new CalcService();

service.square();

There's nothing "private" about that method, just like there's nothing "private" about methods that are attached to AngularJS service objects... The only thing remotely "private" about it is that it happens to belong only to that specific object by virtue of the this keyword.

Community
  • 1
  • 1
Josh Beam
  • 19,292
  • 3
  • 45
  • 68
2

In your example, you are passing a constructor function into the angular service DI method.

In the constructor function you assign a method to this.square .

Just try this without angular and you will see you it behaves thr same.

function Calc() {

    this.square = function() {
        console.log('we get here');    
    } 

} 

var calc = new Calc();
calc.square();

This is the main feature of Javascript's prototype object oriented model. This is plain old OO javascript.

Martin
  • 15,820
  • 4
  • 47
  • 56
  • does the keyword "this" make a property or method public ? what is the reason this wont work without the "this" keyword ? – RoHaN Aug 01 '15 at 07:23
  • The Calc function is a constructor. this has the context of the prototype of the constructor. It would be the same as assigning the method outside the constructor as Calc.prototype.square = function() {...} There are no private properties of the prototype, everything is public. It is common to prefix prototype methods and properties with underscore if they are not meant to be used externally. Any functions or variables defined in the constructor that are not assigned properties of this are not available outside the constructor. – Martin Aug 01 '15 at 07:35
  • The Mozilla documentation tends to be very good. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype – Martin Aug 01 '15 at 07:42
  • when creating multiple objects from this way does all the properties and method duplicate in memory then? – RoHaN Aug 01 '15 at 07:47
  • You should note, when you register a constructor as a service in Angular's DI, angular will only new up one instance. In general each instance will have a new prototype. The methods on the prototype are shared in a way across instanes, but value and object properties are not. – Martin Aug 01 '15 at 07:57
  • can you explain why function Calc() { this.square = function() { console.log('we get here'); } var square = function() { console.log('we get here'); } } like method, "var square" is private and "this.square" is public – RoHaN Aug 01 '15 at 08:16
  • I don't understand your question. – Martin Aug 01 '15 at 08:20
  • need to know why a variable declared as " this.square = some function " is public to outside and other variable declared as var square = some function is not visible to outside. – RoHaN Aug 01 '15 at 08:22
  • Like me and Josh Beam explained, because everything on a prototype is public. I am being patient, but you are essentially asking, "why is everything i add to the prototype on the prototype? " or "why is every public method public?" – Martin Aug 01 '15 at 08:26
  • how do you say that these are on prototype. I log the object and the prototype was empty it was there in the object itself. can you prove it is in the prototype by extending the method because prototype method can be extended – RoHaN Aug 01 '15 at 08:38
  • 1
    Read a book on javascript – Martin Aug 01 '15 at 08:48
1

Above answers does good explanation how service work but they don't explained how this which is newly created object is exposed.

Whenever you create a service angular create a new object of that function for you, and that's get return whenever its get inject in controller, directive, service, etc. Internally method uses prototype of function to create an this which is context of function. Lets look at below code how it work internally.

function CalcService(){
    //The line below this creates an obj object.
    //obj = Object.create(CalcService.prototype)
    //this = obj;
    //`this` is nothing but an instance of function/CalcService.prototype which is giving access to its property attached to this
    var privateVariableExample = 'test'; //this is private variable of service.
    this.square = function(a) {
        //return multiplacation result from here 
    }

    //return this;
}

var objectOfCalcService = new CalcService();
objectOfCalcService.square(1);
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • if the square method is added to the CalcService.prototype why isn't it displaying in _proto_ when I log the object in the console and also prototype enables to override methods, but in this case we can't override using the prototype using CalcService.prototype.somemethod = function(){ return "this is a overridden method"; } – RoHaN Aug 01 '15 at 08:00
  • could you give me a code what you have tried..could you create a fiddle..I'm sure you made some small mistake – Pankaj Parkar Aug 01 '15 at 08:40
  • @RoHaN Glad to help you.Thanks dude – Pankaj Parkar Aug 01 '15 at 08:59