making a function in an object chainable - javascript

I am trying to achieve a chainable object, but cannot figure out how I can do this within a function.
This is how I would like it to work:
$donate.ga('testing').go(value);
My object currently looks like this:
var $donate = {
ga: function (value) {
}
};

You simply need to make each function to return the instance of the object:
var $donate = {
ga: function (value) {
// logic
return this;
}
};

It's already solved here. You must simply return the object in your function.

You need to return the Object like that:
var $donate = {
ga: function (value) {
//after some computation
return this;
},
go: function(val) {
//after some computation
return this;
}
};
If you don't return this (this is a reference to the current Object), you either return undefined or something else and your method defined in your Object is simply out of scope (unknown).

you have to return this; in each sub function before closing it.
for example
Your code
var $donate = {
ga: function (value) {
//perform your code here
return this; // <--- Dont forget to use this before closing the function nest
},
go: function(val) {
//perform your code here
return this; // <--- Dont forget to use this before closing the function nest
}
};

Related

Function definition cannot understand

I know some javascript function declarations. Like exression function, anonymous function, but I do not understand what kind of syntax of these two functions? Can anybody tell me what is the name of these two functions? I mean "manipulateData: function (input)" and "getDataById: function (id)".
Why return statement can have this syntax to return two functions? Why not return one function in one time instead of two functions? It will be great if you can give me some reference documents? Thanks.
app.service('MyService', function ($http, $q, $angularCacheFactory) {
var _dataCache = $angularCacheFactory('dataCache', {
maxAge: 3600000 // items expire after an hour
});
/**
* #class MyService
*/
return {
manipulateData: function (input) {
var output;
// do something with the data
return output;
},
getDataById: function (id) {
var deferred = $q.defer();
if (_dataCache.get(id)) {
deferred.resolve(_dataCache.get(id));
} else {
// Get the data from the server and populate cache
}
return deferred.promise;
}
};
});
These functions are just anonymous functions that happen to be values in an object. Consider this:
var object = {
add: function(x, y) {
return x + y;
}
};
object.add(1, 2); // = 3
This is the same as:
function addFunction(x, y) {
return x + y;
}
var object = {
add: addFunction
};
object.add(1, 2); // = 3
There's nothing special about these functions, as they're just normal properties of an object.
You are not returning a function in this case but an Object.
When you define a service in angularjs you have to provide its implementation in the callback (the second argument of app.service)
This callback has to return methods you want to make available to other parts of your application.
Then in a controller or in another service you will be able to write:
app.controller("MyCtrl", ["MyService", function(MyService) {
MyService.getDataById('an id');
}]);
Angular Service returns an instance of the service you bind to the app namespace, those functions in the return statement are public methods that can be worked with. Basically an Object that contains two methods manipulateData, and getDataById.
It's similar to this
function company() {
let product; // This is private
// Public Methods
return {
setLatestProduct: function(value) {
product = value;
console.log(product, ' set');
},
getLatestProduct: function() {
return product;
}
}
}
const apple = company();
console.log(apple); // { setLatestProduct: function, getLatestProduct: function }

Data structure adding and removing items using constructor functions

Its the beginning of a data structure exercise and I am trying to write an add and remove function -its should be so simple and I don't get why its wrong?! Also the way to do it 8using a constructor function, prototype etc. must stay the way it is)
Any help much appreciated!
function Thestack () {
this.array=[];
}
Thestack.prototype.plus = function (i) {
this.array.push(i);
return this; // cannot be edited
};
Thestack.prototype.minus = function () {
this.array.pop();
};
var smallstack = new Thetack();
smallstack.plus(something); //followed by
smallstack.minus();
should return: something
your minus function does not have a return statement, so it just returns undefined by default
You could as in the add function return this so you can continue chaining of methods, return the element removed or return the length of the remaing array
// return this for chaining
Thestack.prototype.minus = function () {
this.data.pop();
return this;
};
// return the removed item
Thestack.prototype.minus = function () {
//edits the data array in place and returns the last element
return this.data.pop();
};
// return the length of the remaining array
Thestack.prototype.minus = function () {
this.data.pop();
return this.data.length;
};

How to dynamically change a function

I have a function that has already been assigned and I would like to append some additional script. When I display the function like:
var func = obj.when_clicked;
alert(func);
The following is displayed:
function object_123(){
object_123_Action();
}
The type is a "function" and the function is executed elsewhere which I cannot change, the code is:
this.when_clicked();
I need to modify the function by appending my own code so it becomes:
function object_123(){
object_123_Action();
my_clicked(obj);
}
Then add that back and over write the when_clicked function.
It does work if I manually add the code like:
obj.when_clicked = function object_123(){object_123_Action();my_clicked(obj);};
However, I do not know what is in the function initially, all I want is to append the:
my_clicked(obj);
I do need the obj to be the actual object of interest which is obj.
You can wrap it:
var f = this.when_clicked;
this.when_clicked = function() {
// Call the original
var rv = f.apply(this, arguments);
// your code here
// Return the original function's return value
return rv;
};
Function#apply calls the original with the specified this flag. arguments is provided by the JavaScript engine: It's a pseudo-array of the arguments your function was called with, so the above just passes all of them on.
Be sure to think about what it means if your function throws an exception, and catch them if you want to suppress them.
If you do this often, you can giev yourself a utility function:
function wrapFunction(f, wrapper) {
return function() {
var rv = f.apply(this, arguments);
wrapper.apply(this, arguments);
return rv;
};
}
Then
this.when_clicked = wrapFunction(this.when_clicked, function() {
// Your code here
});
Or if you want access to the original's return value, potentially changing it:
function wrapFunction(f, wrapper) {
return function() {
var rv = f.apply(this, arguments);
rv = wrapper.call(this, rv, arguments);
return rv;
};
}
Then
this.when_clicked = wrapFunction(this.when_clicked, function(rv, args) {
// Your code here, using `rv` and `args`, which is a pseudo-array
// Potentially update `rv`
return rv;
});
You can store your functions in an array on the object.
Then, loop though the functions in another function and execute them.
var myObj = { 'myfunctions': [ ] };
and to add functions:
myObj.myFunctions.push (function () { /*function code here*/ });
Or if you already have a named function:
myObj.myFunctions.push (nameOfFunction);
And to call all the functions, use this function (don't add this function to myObj)
function executeMyFunctions (myObj) {
for (var i = 0; i < myObj.myFunctions.length; i++) {
myObj.myFunctions[i]();
}
}
Used this answer on another question of #peter. Meant to post here.

trying to use a closure with parameters as a callback

I have a library function that I'm calling from a method. It takes a callback with one parameter that I would like to be another method from the same object. I can't seem to get the syntax right. Here's what I've got:
myOriginalObject.login = function() {
// inside a method
var obj = this;
var closure = function(token) { return function() { obj._login2(token); } }
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, closure );
// .. some more code and method ends
}
myOriginalObject._login2 = function(authResult)
{
// .. I can't get this function called by the gapi library
}
P.S. sorry if this post isn't done properly (still learning) thanks!!!
You're passing a reference to the closure function to authorize, but I think you want to call it and pass the reference to the function it creates. So:
// `token` argument here ------------------v
var closure = function() { return function(token) { obj._login2(token); } }
// not here------------^
and
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, closure() );
// Call it -----------------------------------------------^^
You may not need the closure function at all, but it's hard to tell without knowing more about the surrounding code. But this may well be all you need:
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, function(token) {
obj._login2(token);
});
Side note: Since myOriginalObject is a singleton, you don't need the var obj = this;, you can just use the symbol myOriginalObject directly:
$window.gapi.auth.authorize({"client_id": this.clientId,
"immediate":false,
"response_type":"token",
"scope":this.scopes}, function(token) {
myOriginalObject._login2(token);
});
This line:
var closure = function(token) { return function() { obj._login2(token); } }
will return a function, i.e. the return value of closure() is a function.
One solution:
change
var closure = function(token) { return function() { obj._login2(token); } }
to
var closure = function(token) { obj._login2(token); }

javascript closure: protecting inner variable

I'm using the revealing module pattern somewhat like this:
var SomeClosure = function () {
var SomeInnerVar = 4;
function InnerGetTheVar() {
return SomeInnerVar;
}
function InitClosure() {
// there's something else happening here that requires me to
// wait for document.ready before initializing the closure
setInterval(IncreaseSomeInnerVar, 10000);
}
function IncreaseSomeInnerVar() {
SomeInnerVar = SomeInnerVar + 1;
}
InitClosure();
return {
GetTheVar: InnerGetTheVar
}
}
$(document).ready(function () {
SomeClosure = SomeClosure();
});
Now why is it that if in the console I type this:
SomeClosure.GetTheVar = 2;
SomeClosure.GetTheVar; // outputs 2!
Why doesn't the closure keep SomeInnerVar protected? I don't want the outer scope to be able to change SomeInnerVar like that.
Thanks for your suggestions.
Actually, SomeInnerVar is still 'protected', in this sense. However, you are overwriting SomeClosure's GetTheVar attribute with the value 2, which isn't 'protected' in the same sense. In other words, you aren't modifying SomeInnerVar, you're modifying GetTheVar.
Instead of just returning an object literal, use Object.defineProperty:
var out = {};
if ( Object.defineProperty ) {
Object.defineProperty(out, 'GetTheVar', {
value: InnerGetTheVar,
writable: false
});
} else {
out.GetTheVar = InnerGetTheVar;
}
return out;

Categories

Resources