How to Define a function to invoke like this: function1().function2()? - javascript

function1().function2();
How to Define a function to invoke like this?

In addition to the other answers, you usually would do this when coding a fluent interface, where you are returning the parent object to allow method chaining, which you could do like so:
var calculator = (function() {
var i = 0;
var public = {};
public.add = function(a) { i += a; return public; }
public.sub = function(a) { i -= a; return public; }
public.equals = function() { return i; }
return public;
})();
console.log(calculator.add(2).sub(3).add(20).equals());

here you have a working example, you can call function1 and get the object mapping to the functions that you desire.
function function1() {
return {
function2: f2
}
}
function f2() {
return "do something";
}
console.log(function1().function2())

You'll need function1 to return an object that has a property of function2. For example:
function f1() {
return {
f2() {
console.log('foo');
}
};
}
f1().f2();

Related

Why does object prototype methods have no caller in oop unlike in procedural programming

If I have a procedural function calling another procedural function like this:
function awesome() {
return arguments.callee.caller.name;
}
function ridiculous() {
return awesome();
}
ridiculous();
Then I get back the caller named "ridiculous". But when I write it in oop-style, then the caller is null.
function myObj() {}
myObj.prototype.awesome = function() {
return arguments.callee.caller.name;
}
myObj.prototype.ridiculous = function() {
return this.awesome();
}
I wonder, why this happens and how to get back the caller anyway.
The key in the object and the name of the function isn't the same thing.
Take a look at my snippet:
function myObj() {}
myObj.prototype.awesome = function awesome() {
return arguments.callee.caller.name;
}
myObj.prototype.ridiculous = function ridiculous() {
return this.awesome();
}
var o = new myObj();
console.log(o.ridiculous())
It's because when declaring methods on prototype you should be using named functions.
such as:
function myObj() {}
myObj.prototype.awesome = function awesome() {
return arguments.callee.caller.name;
}
myObj.prototype.ridiculous = function ridiculous() {
return this.awesome();
}
myObj.prototype.ridiculous()

scope of "this" in async function of ionic angular app

I'm trying to execute a function, which is not found, UNLESS I save a reference to the function in a seperate variable:
function updateCheck() {
if (this.isNewVersionNeeded()) {
var buildFunc = this.buildObject();
this.updateBiography().then(function(){
buildFunc();
})
}
};
The buildObject function only executes if I save it before executing this.updateBiography (async function) and execute it via the variable I saved it in (buildFunc).
The following does NOT work:
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
this.buildObject();
})
}
};
I expose all functions via a service object:
var service = {
all: all,
updateBiography: updateBiography,
get: get,
updateCheck: updateCheck,
isNewVersionNeeded:isNewVersionNeeded,
buildObject:buildObject
};
return service;
When I log the "this" object while Im right before the execution of buildFunc, it logs window/global scope. Why is this and how should I deal with this? I do not want to save all my async methods in a seperate variable only to remember them. How should I deal with this problem and why does it not work?
The entire service:
(function () {
angular
.module('biography.services', [])
.factory('Biography', Biography);
Biography.$inject = ['$http'];
function Biography($http) {
var biographyObject = { } ;
var service = {
all: all,
updateBiography: updateBiography,
get: get,
updateCheck: updateCheck,
isNewVersionNeeded:isNewVersionNeeded,
buildObject:buildObject
};
return service;
var self = this;
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
self.buildObject();
})
}
};
function updateBiography() {
return $http.get("Apicall adress")
.then(function (resp) {
window.localStorage.setItem('biography', resp.data);
window.localStorage.setItem('biographyTimeStamp', Date.now());
}, function (err) {
console.log('ERR', err);
});
}
function all() {
return biographyObject;
}
function get(name) {
var biography = biographyObject;
for (var i = 0; i < biography.length; i++) {
if (biography[i].name === name) {
return biography[i];
}
}
return null;
}
function buildObject() {
var temp = JSON.parse(window.localStorage.getItem('biography'));
biographyObject = temp;
};
function isNewVersionNeeded() {
prevTimeStamp = window.localStorage.getItem('biographyTimeStamp');
var timeDifference = (Date.now() - prevTimeStamp);
timeDifference = 700000;
if (timeDifference < 600000) {
return false;
}
else {
return true;
}
}
}
})();
The context (different from function scope) of your anonymous function's this is determined when it's invoked, at a later time.
The simple rule is - whatever is to the left of the dot eg myObj.doSomething() allows doSomething to access myObj as this.
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function() {
// whichever object has this anonymous function defined/invoked on it will become "this"
this.buildObject();
})
}
};
Since you're just passing your function reference, you can just use this
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(this.buildObject);
}
};
and if this.buildObject is dependent on the context (uses the this keyword internally), then you can use
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(this.buildObject.bind(this));
}
};
this is determined by whatever context (object) the function is invoked on, and it appears that an anonymous function, or a function not referenced through an object defaults to having a window context. the bind function replaces all instances of this with an actual object reference, so it's no longer multi-purpose
same function invoked in different contexts (on different objects)
var obj = {
a: function () {
console.log(this);
}
};
var aReference = obj.a;
aReference(); // logs window, because it's the default "this"
obj.a(); // logs obj
The reason is here 'this' refers to callback function.You can't access 'this' inside callback.Hence solution is,
function Biography($http) {
var self = this;
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
self.buildObject();
})
}
};
Using ES6 syntax:
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(()=>{
this.buildObject();
})
}
};

How do I chain call functions?

Hey guys am new to javascript app development
When i tried this code
function name() {
return 5;
}
function anotherone() {
return 3;
}
function horse() {
return 5;
}
When i called the function like console.log(name().anotherone().horse()); ..it throws me error like undefined not a function.
Is it possible to call function like afunction().anotherfunction().anotherfunction1() in javascript ??
Thanks in advance..
When you callname().another(), this evaluates to (5).anotherone().
anotherone() is not a function of the literal 5, which is why you get the error undefined is not a function. If you want to chain methods, use a class/object that returns an instance of itself so you can call myClass.aFunction().anotherfunction() so the call stack evaluates to (myClass).anotherfunction()
Yes it is. Every function but the last in the chain have to return the object containing the function you call next, for example:
var obj = {
foo: function(){ return obj; },
bar: function(){ return obj; },
baz: function(){ return 123; }
};
console.log(obj.foo().bar().baz()); // works, logs 123
Read more about OOP in javascript
var Class = function () {};
Class.prototype = {
value: 0,
addOne: function () {
// do stuff
this.value++;
return this;
},
addTwo: function () {
this.value = this.value + 2;
return this;
},
getValue: function () {
return this.value;
}
};
var obj = new Class();
// Chaining possible when you return the object at the end of your method
console.log(obj.addOne().addTwo().addOne().getValue()); // returns 4
// Chaining is not possible when you return something else
console.log(obj.addOne().getValue().addOne()); // undefined is not a function
The problem is your syntax.
Look at your functions: the first returns 5, so you're essentially doing 5.anotherone(). Dot notation is for accessing properties and methods of an object. anotherone() is not a method of 5, so you'll get undefined is not a function.
Also, you don't provide any arguments for the functions, so you can't pass anything to them.
You can kind of do what you're describing, but you have to go about it a bit differently:
function name() {
return 5;
}
function anotherone(num) {
return num + 3;
}
function horse(num) {
return num + 5;
}
console.log(horse(anotherone(name())));
Demo
Its quiet easy:-
function name() {
return 5;
setTimeout(anotherone,0);
}
function anotherone() {
return 3;
setTimeout(horse,0);
}
function horse() {
return 5;
}
Now you just need to call the first function and it will call the next one itself.

Rewiring a JavaScript function

Let's say I have a function named fna() that does a simple thing such as:
var fna = function(ar) {
console.log("argument: ", ar);
return "return value is argument too: " + ar;
}
fna() is coded by some other developer and I can't access to it. He didn't bother casting any events and when it is called, I have to be aware of it. Hopefully, his method is accessible by window.fna().
I want some additional code to be executed. Let's say, add this console.log
var fna = function(ar) {
console.log("Hola, I am some additional stuff being rewired");
console.log("argument:", ar);
return "return value is argument too: " + ar;
}
And I want this to be executed even when called from fnb() by some other part of the code.
var fnb = function() {
return fna("Bonjour, I am fnb and I call fna");
}
Here is a way I found, using the utils.rewire() method. utils is just some utility belt, and it could be added to your favorite framework as a plugin. Unfortunately, it only works on Firefox.
var utils = utils || {};
// Let's rewire a function. i.e. My.super.method()
utils.rewire = function(functionFullName, callback) {
var rewired = window[functionFullName];
console.log("%s() is being rewired", functionFullName)
window[functionFullName] = function() {
callback();
return rewired.apply(this, arguments);
}
}
Use it like this.
utils.rewire("fna",function(){
console.log("Hola, I am some additional stuffs being rewired");
});
This seems to work such as shown in this jsbin, but (and here is my question:) How do I rewire obja.fna()?
var obja = {
fna = function(ar) {
console.log("argument:", ar);
return "return value is argument too: " + ar;
}
};
I cannot make it work to rewire the some.object.method() method.
Extra bonus question: Is there a more cleaner way to do this? Out-of-the-box clean concise and magic library?
Refactor rewire into a rewireMethod function which acts on any given object:
var utils = utils || {};
utils.rewireMethod = function (obj, functionName, prefunc) {
var original = obj[functionName];
obj[functionName] = function () {
prefunc();
return original.apply(this, arguments);
};
};
Note that rewire can now be written as:
utils.rewire = function (functionName, prefunc) {
utils.rewireMethod(window, functionName, prefunc);
};
Then you just call it as:
utils.rewireMethod(obja, "fna", function () {
console.log("Hola, I am some additional stuff being rewired");
});
Note that nothing special is required if you have a method like window.ideeli.Search.init(). In that case, the object is window.ideeli.Search, and the method name is init:
utils.rewireMethod(window.ideeli.Search, "init", function () {
console.log("Oh yeah, nested objects.");
});
Add a parameter to rewire that is the object containing the function. If it's a global function, pass in window.
var utils = utils || {};
// let's rewire a function. i.e. My.super.method()
utils.rewire = function(object, functionName, callback) {
var rewired = object[functionName];
console.log("%s() is being rewired", functionName)
object[functionName] = function() {
callback();
return rewired.apply(this, arguments);
}
}
utils.rewire(some.object, "method", function(){} );
You can simply use a closure to create a generic hook function that allows you to specify another function to be called immediately before or after the original function:
function hookFunction(fn, preFn, postFn) {
function hook() {
var retVal;
if (preFn) {
preFn.apply(this, arguments);
}
retVal = fn.apply(this, arguments);
if (postFn) {
postFn.apply(this, arguments);
}
return retVal;
}
return hook;
}
So, for any function that you want to hook, you just call hookFunction and pass it the function you want to hook and then an optional pre and post function or yours. The pre and post function are passed the same arguments that the original function was.
So, if your original function was this:
var fna = function(ar) {
console.log("argument:",ar);
return "return value is argument too:"+ar;
}
And, you want something to happen every time that function is called right before it's called, you would do this:
fna = hookFunction(fna, function() {
console.log("Hola, I am some additional stuff being rewired right before");
});
or if you wanted it to happen right after the original was called, you could do it like this:
fna = hookFunction(fna, null, function() {
console.log("Hola, I am some additional stuff being rewired right after");
});
Working demo: http://jsfiddle.net/jfriend00/DMgn6/
This can be used with methods on objects and arbitrary nesting levels of objects and methods.
var myObj = function(msg) {
this.greeting = msg;
};
myObj.prototype = {
test: function(a) {
log("myObj.test: " + this.greeting);
}
}
var x = new myObj("hello");
x.test = hookFunction(x.test, mypreFunc2, myPostFunc2);
x.test("hello");
Based on Claudiu's answer, which seems to be the most appreciated way, here is a solution using a for loop and proxying the context... But still, I find this ugly.
var utils = utils || {};
// Let's rewire a function. i.e. My.super.method()
utils.rewire = function(method, callback) {
var obj = window;
var original = function() {};
var tree = method.split(".");
var fun = tree.pop();
console.log(tree);
// Parse through the hierarchy
for (var i = 0; i < tree.length; i++) {
obj = obj[tree[i]];
}
if(typeof(obj[fun]) === "function") {
original = obj[fun];
}
var cb = callback.bind(obj);
obj[fun] = function(ar) {
cb();
return original.apply(this, arguments);
}
}
Well, this looks strange. Consider this
function wrap(fn, wrapper) {
return function() {
var a = arguments;
return wrapper(function() { return fn.apply(this, a) })
}
}
Example:
function foo(a, b) {
console.log([a, b])
return a + b
}
bar = wrap(foo, function(original) {
console.log("hi")
var ret = original()
console.log("there")
return ret
})
console.log(bar(11,22))
Result:
hi
[11, 22]
there
33
To wrap object methods, just bind them:
obj = {
x: 111,
foo: function(a, b) {
console.log([a, b, this.x])
}
}
bar = wrap(obj.foo.bind(obj), function(fn) {
console.log("hi")
return fn()
})

Assigning multiple methods to an application in JavaScript

I have now officially spent all day trying to assign a variable in JavaScript!
Forgive me for asking this same question 4 different ways, but here's what I started out with this morning, and this works. I just need to add a second method to it now.
Application = {};
(function() {
var closure = {};
Application.myFirstMethod = function() {
if (arguments.length) {
closure = arguments[0];
} else {
return closure;
}
}
})();
Application.myFirstMethod(3.14);
result = Application.myFirstMethod();
log(result);
So my question is: and please be patient with me, if I add mySecondMethod to Application, then how do I keep the value of arguments[0] without using the variable that is currently called closure?
How about this, it defines a function that takes a string and returns a getter/setter function. The string is used to indicate what property to get/set the value as in variables.
Demo
Application = {};
(function() {
var variables = {};
Application.myFirstMethod = makeGetterSetter('myFirst');
Application.mySecondMethod = makeGetterSetter('mySecond');
function makeGetterSetter(name) {
return function () {
if (arguments.length) {
variables[name] = arguments[0];
} else {
return variables[name];
}
};
}
})();
Application.myFirstMethod(4);
result1 = Application.myFirstMethod();
Application.mySecondMethod(5);
result2 = Application.mySecondMethod();
console.log(result1);
console.log(result2);
If you wanted to have a getter or setter with custom logic in it before either event then it would be easiest to just define them separately. Stick with the this[property] pattern to keep all your fields in one spot.
Application.myCustomMethod = function() {
if (arguments.length) {
// some logic
variables['custom'] = arguments[0];
} else {
// some logic
return variables['custom'];
}
}
It looks like you are searching for adding properties to objects, in the Prototype-Oriented Programming Language sense of the term; just use the "this" object, which stands for the current calling context, and which will be set to your Application object when calling the methods:
Application = {};
(function() {
Application.myFirstMethod = function() {
if (arguments.length) {
this.foo = arguments[0];
} else {
return this.foo;
}
};
Application.mySecondMethod = function() {
if (arguments.length) {
this.bar = arguments[0];
} else {
return this.bar;
}
};
})();
Application.myFirstMethod(3.14);
console.log(Application.myFirstMethod());
Application.mySecondMethod(2097);
console.log(Application.mySecondMethod());
console.log(Application.myFirstMethod());
Here's what I figured out. I probably need to use the word new somewhere though.
Application = {};
(function() {
Application.myFirstMethod = FirstMethod();
Application.mySecondMethod = SecondMethod();
function FirstMethod() {
var closure = {};
return function(myArgument) {
if (arguments.length) {
closure.result = arguments[0]; // myArgument
} else {
return closure.result;
}
}
}
function SecondMethod() {
var closure = {};
return function(myArgument) {
if (arguments.length) {
closure.result = arguments[0]; // myArgument
} else {
return closure.result;
}
}
}
})();
Application.myFirstMethod(3.14);
result = Application.myFirstMethod();
log(result);
Application.mySecondMethod(2013);
result = Application.mySecondMethod();
log(result);

Categories

Resources