javascript pattern used in angular - javascript

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);
}
});

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.

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.

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);

Related

I want access of a property of my class in a static metod, how can i do? is it possible? [duplicate]

I have a code like that:
User = function(){}
User.a = function(){
return "try";
}
User.b = function(){
}
​
From User.b() I can call User.a() using:
User.b = function(){
return User.a();
}
but not using this since it's not an instance of user (User.a() and User.b() are something like "static methods").
What i want to do is to be able to call User.a() from User.b() without knowing which is the main function, in this case User.
Something like this to be used in static methods.
In reality there is no methods or static methods in js, there's just functions that are assigned to object properties (functions being objects as well) and they all work the same way. Since you are calling it like User.b(), this will be User for the call.
User.b = function() {
return this.a();
}
The only thing that determines the context of the function is how you call it.
If you call it using a plain identifier (a function name, a variable or a property), the context will be the global window object:
someFunction();
If you call it using a period to access an object member, the context will be the object:
someObject.someFunction();
If you copy a member from an object to a variable, there is no connection to the object any more, and it will be called with window as context:
var x = someObject.someFunction;
x();
If you assign a function as a property to an object, and call it using the object, the context will be the object:
someObject.x = someFunction;
someObject.x();
For your specific case, User is a function, which also is an object.
If you call the function using User.b, its context will be the User object, which happens to be a function in this case. From within the function you can still use this to access the context:
User.b = function(){
return this.a();
}
You don't have normal inheritance in javascript. I guess you are trying to do something like this:
User = function(){
this.a= function(){
return 'try';
}
this.b= function(){
return this.a();
}
}
This way User becomes a constructor. Each new instance of User will have acces to these methods. So if you want to create a new instance of the User class, you can use the new keyword:
var client= new User()
and then you'll have access to all the methods from user using client
client.b() //returns 'try'
Well, functions exist independently of their container objects; they're just values. So if you're not calling them as methods on an object, they inherit whatever this is in the calling context. In that case, expecting them to know about their container would be the same as assigning User.x the value 1 and then expecting the number 1 to somehow know about User.
However, when you call User.a() or User.b(), you are in fact calling them as methods - methods of the (function object) User. So this will be the same as User, and b can just call this.a() and you should be good to go.

I just started to learn Angular JS Framework and I get something extremely weird

Singleton
A singleton is a particular kind of class that, can be instantiated only once,
According to the angularJs Documents, Service and Factory are Singleton.
So if we define app.service('b', fn) like this
As per documents Angular JS call the Service like
cache.b = new fn(); so b’s stored value comes from newing fn.
So I can understand angular create instance itself so we cannot create new instance again so service is singleton.
But when define app.factory(‘a’, fn) like this, a's stored value comes from running fn.
Angular call cache.a = fn();
So there is not ‘new’ or oops concept. So where is comes here Object concept for instantiate and how is factory also singleton? Because of A singleton is a particular kind of class that, can be instantiated only once.
Will be Appreciate if answer.
You're right, angular does instantiate a factory using
cache.a = fn();
but before this code it checks whether the cached variable is not an object.
Therefore, the complete code may be as follows
if (\\Check whether cache.a is not an object){
cache.a = fn();
}
In factories, you instantiate a class and return the object, angularjs calls the factory function and caches the returned value somewhere. When you try to inject the factory somewhere every time, it checks whether the cached variable is not an object and if angularjs finds that the variable is not an object, it calls the factory function.

Issue related to declaring Variable in Famo.Us

I have Small application in Famo.us Framewok.
I want to declare array variable that can be use in calling js.
I have 2 .js file: (1) PageView.js (2) GetContent.js
(1) PageView.js
function AddContent() {
View.apply(this, arguments);
var getContent = new GetContent();
getContent.AddPages();
(2)GetContent.js
function GetContent() {
View.apply(this, arguments);
}
GetContent.prototype = Object.create(View.prototype);
GetContent.prototype.constructor = GetContent;
GetContent.DEFAULT_OPTIONS = {};
GetContent.prototype.AddPages = function () {
GetData();
}
I want to declare array variable in GetContent.js file that can be accessible in PageView.js using the object of GetContent defiened in PageView.js in above code.
so that i can use like getContent.variablename[1]
how to achieve it?
Your GetContent class would need to have an array assigned to it's instance like so:
this.variablename[1, 2, 3];
Adding this allows your array to be attached to the class's specific instance. Otherwise, your array will only exist for the lifetime of the function scope you create it in.
You may also find that you can't access the getContent object after it's been created in your PageView for the same reason. Instead try this.getContent = new GetContent();
Lastly, try to avoid directly accessing other class's variables directly. Instead, use getter/setter methods which allow the class to share and modify their data securely.

Prototype / class / public attributes in JavaScript

I have a constructor for a model (similar to Backbone model) which uses an instance of a store (e.g. MongoDB / Redis) which is passed to the model factory. Now inside the constructor for the model, I do
this.store = options.store;
Store is now available as this.store once I construct an instance with var model = new Model().
Then I faced a situation when I my Model has "public" methods, e.g. Model.find() which will work without instantiating the model. But now because it's not been instantiated, functions inside Model can not access store by this.store.
What I did, is I started also adding store to the constructor itself Model.store = options.store which fixes the problem. But now store is exposed to anything that uses Model constructor and this is not desirable.
I am guessing I am doing something wrong. So I would appreciate some help.
If I get what you're saying correctly, then I think what you want is to allow for a "static" find() method on Model without exposing the store variable. Javascript doesn't really have a formal private scope for classes, but you can get what you want using closures. Here's a fiddle:
http://jsfiddle.net/52FPy/
EDIT:
An updated fiddle to demonstrate various ways to expose/hide info using closures:
http://jsfiddle.net/52FPy/2/
Briefly:
var Model = function(){
var store = 'this is a store';
var Model = function(){
}
Model.find = function(){
return store;
}
return Model;
}()
This will "hide" the store variable in the way you want.

View Model inheritance when using Durandal

I am building an application using Durandal and I have the need to share some functionality across view models.
I have 5 screens to build and they are all virtually the same screen except that in the activate function they will call to a different api end points but otherwise the view and view models will be identical.
Is there a pattern that I should be following to structure this correctly to promote code reuse?
If the views and the view models are identical except for calling different api actions, what about just taking in a parameter as part of the route? Then in the activate function, you can switch on the parameter. The route values can be designated so that your url is relevant, like [http://site/page/subtype], where subtype is the parameter (instead of using numeric values)
Regarding inheritance, depending on the features you need, there's so many ways to do JavaScript inheritance it can be a little confusing. There are some full-featured inheritance models provided by libraries such as base2 and Prototype. John Resig also has an inheritance model that I've used successfully.
In general, I prefer to stick to simpler solutions when it comes to JS inheritance. If you need a pretty much the full set of inheritance features, those libraries are good to consider. If you only really care about accessing a set of properties and functions from a base class, you might be able to get by with just defining the view model as a function, and replacing the function's prototype with the desired base class. Refer to Mozilla's Developer Docs for good info on inheritance.
Here's a sample:
//viewModelBase
define(function (require) {
"use strict";
function _ctor() {
var baseProperty = "Hello from base";
function baseFunction() {
console.log("Hello from base function");
}
//exports
this.baseProperty = baseProperty;
this.baseFunction = baseFunction;
};
//return an instance of the view model (singleton)
return new _ctor();
});
//view model that inherits from viewModelBase
define(function (require) {
"use strict";
function _ctor() {
var property1 = "my property value";
function activate() {
//add start up logic here, and return true, false, or a promise()
return true;
}
//exports
this.activate = activate;
this.property1 = property1;
};
//set the "base"
var _base = require("viewModelBase");
_ctor.prototype = _base;
_ctor.prototype.constructor = _ctor;
//return an instance of the view model (singleton)
return new _ctor();
});
Keep in mind this example all results in what effectively is a singleton (i.e. you'll only get the same instance, no matter how many times you require() it)
If you want a transient (non-singleton) just return _ctor. Then you'll need to instantiate a new instance after you require() it.
One more note, in general, functions should be defined on the prototype, not within the constructor function itself. See this link for more information on why. Because this example results in only a single instance, it's a moot point, so the functions are inside the constructor for improved readability and also the ability to access the private vars and functions.

Categories