Detect the caller and called it - javascript

I want to recognize the calling function and one function call it that
The following example illustrates this issue
<script>
var func = (function () {
var check = function (value) {
//detect caller function
var that = arguments.callee.caller;
//I want
//if Buttom One click --> call print in func1
//if Buttom Two click --> call print in func2
};
return {
check:check
}
})();
var func1 = (function () {
var start = function () {
func.check(10);
};
var print = function (value) {
alert(value);
}
return {
start: start,
print: print
}
})();
var func2 ...
</script>
<button id="One" onclick="func1.start()">One</button>
<button id="Two" onclick="func2.start()">Two</button>
Do you have a solution?
Many thanks!

Putting aside the fact that arguments.callee and Function.caller are both non-standard, the reason why it doesn't work is that you are confusing properties with local variables, all that mixed in with closures.
var func1 = (function () {
// ...
})();
This creates a function, runs it and saves the result in func1. Since the return statement of your closure is return { start: start }, at the end of this section of code func1 will contain an object which as a method called start.
When you use var, you're only creating a variable which exists inside that function. Outside of the function, it is no longer accessible. You did store the start function in the returned object, but you never returned print so it doesn't exist anymore.
Instead of going line by line and trying to explain all what is wrong, I'll ask you this: what you were actually trying to do? Don't ask us about your attempted solution which didn't work, but about what the code should do.
I suggest you look at these answers I wrote if you need further explanations on closures and scope.
Understanding public/private instance variables
Do the different methods of creating classes in Javascript have names and what are they?

Related

Javascript - self-executing functions : why to use them if I can create local scope with not self-executing functions?

I know there are a lot of posts here and elsewhere about selfexecuting functions but I still have some questions after reading posts.
why would I ever assign a self-executing function to a variable? If seems that they execute themselves anyways.
var myFunc=(function() {
console.log('Hello World');
})();
I read a lot that the reason to use self-executing functions is to keep variables private. If I have a not self-executing function, everything I define inside that function is gonna be private anyways?!
(function() {
var name="my Name"
console.log(name);
})();
vs.
function() {
var name="my Name"
console.log(name);
};
//its the same
So I dont quite understand how self-executing functions are to keep local scope (as you can do that using not self-executing functions) so the only reason I see is to use them when you want to execute automatically for example on page load.
Thanks!
just one more question:
var test=(function myFunc(){
var name="Hello World"
return {
test1: function(){
return name;
},
test2:function(){
return name+"1"
}
}
})()
test.test1()
vs
var test=function myFunc(){
var name="Hello World"
return {
test1: function(){
return name;
},
test2:function(){
return name+"1"
}
}
}
test.test1()
--> what exactly happens here that because of IIFE I can actually execute test.test1() and not with a regular function?
You usually wrap your functions in a anonymous function when you want to keep your scope contained. This is also part of the module pattern which is still pretty popular:
https://toddmotto.com/mastering-the-module-pattern/
Then you can assign the outcome of that IIFE to a variable so your scope can only be accessed by calling that variable.
myScope.myLocallyScopedProperty or myScope[myLocallyScopedProperty]
Your other function needs to be called manually and it also accessible from anywhere.
I suggest reading the article by Todd Moto it explains a lot.
If that IIFE doesn't return anything, then there's indeed absolutely no use to assign it to anything. Though there may of course be examples of IIFEs returning something you want to use later; in that case the IIFE is a private scope to set up some object for example:
var foo = (function () {
var bar = 'something';
// here be dragons
return baz;
})();
This gives you a private scope to assemble baz without unnecessarily leaking temporary variables into the global scope.
There's no difference in those examples, except that the second one doesn't execute and therefore never does anything. Scoping and the purpose for the scoping are unchanged.
First, briefly, these are not self-executing functions. (That would be a recursive function.) These are inline-invoked function expressions (IIFEs). The function doesn't call itself, the expression calls the function.
why would I ever assign a self-executing function to a variable?
That's not what that code does. It assigns the result of calling the IIFE to the variable. You'd use it when you want that result, for instance:
var x = (function() {
var n = 0;
return {
increment: function() { return ++n; }
};
})();
console.log(typeof x); // "object"
console.log(x.increment()); // 1
console.log(x.increment()); // 2
x doesn't receive the IIFE, it receives what that IIFE returns — in this case, an object with a function on it.
I read a lot that the reason to use self-executing functions is to keep variables private. If I have a not self-executing function, everything I define inside that function is gonna be private anyways?!
Yes, that's true. You use an IIFE when you only need to do what's inside the IIFE once. Otherwise, absolutely, you define the function, give it a name, and then reuse it wherever you need it. The variables inside the function are indeed private to it (unless exposed in some way), and are specific to each call to the function.
1: To assign an IIFE to a local Variable makes sense for something like that:
var getID = (function () {
var id = 0;
return function () { return id++; };
})();
This way you can get new IDs without running the risk to reset the internal counter from anywhere else in the code, except by redeclaring the variable.
2: Basically you create Scope by creating a function. But if you do not execute it, well, it doesn't do anything. So if you have that:
function () { return 'foo' };
How do you want to call it if it is not assigned to a variable or does not have a name? By itself it wont do anything, since it is not called. Something like that is dead code and can safely be removed.
your first thing has no sense whatsoever:
var myFunc = =(function() {
console.log('Hello World');
})();
myFunc is not a function and it is undefined.
The sense, as I see it, for a self executing function is to package some code that has to be executed right away.
var p1=1, p2=2, obj = {
prop: (function(x,y){ return x+y;})(p1, p2)
}
OR
avoiding overwriting already defined functions/objects in the case your script will be inserted in a already existing application and also creating a kind of private methods, if you like:
function aFunction() {
console.log('a code');
}
(function(w) {
function aFunction() {
console.log('b code');
}
w.run = function() {
aFunction();
};
})(window)
aFunction();
run();
You use self executing functions to expose only what you need out of a scope. I think I have a somewhat clear example:
let myObject = (function(){
let privateVariable = "I'm private";
function privateMethod() {
//private method
};
function methodToExpose() {
//this method I will expose
}
//what is returned here, is what is public
return {
PublicMethod: methodToExpose
//other public properties
}
}());
So, the function gets executed immediately, and what happens is I have an object that is defined by what I returned from the function.
Another example I could give you is to retain variables of the current scope inside a closure, but you wouldn't really use it that much, since we now have let. A practical example:
<span id="1">old</span>
<span id="2">old</span>
<span id="3">old</span>
<span id="4">old</span>
<script>
var toPrint = "";
for (var i = 1; i <= 4; i++) {
toPrint = "new: " + i;
document.getElementById(i.toString()).addEventListener('click', function(event){ event.target.innerHTML = toPrint; })
}
</script>
When you click on a span, the value will be replaced with the value... "new: 4"!
That's because when you finished executing, that's the value that toPrint has. The function assigned to the click event retrieves that toPrint, and at the time it retrieves it, it is "new: 4". We solve this with closures:
<span id="1">old</span>
<span id="2">old</span>
<span id="3">old</span>
<span id="4">old</span>
<script>
var toPrint = "";
for (var i = 1; i <= 4; i++) {
toPrint = "new: " + i;
document.getElementById(i.toString()).addEventListener('click', function(event){
var currPrint = toPrint;
return function(event){ event.target.innerHTML = currPrint ; };
}())
}
</script>
By using a self executing function, we save the current value of toPrint in the currPrint variable inside a local scope. When we later click on a span, the function assigned to the click even will use the variable currPrint, which contains the value that toPrint had at the time the function was assigned, not the value that toPrint has at finished execution.
Note that this is solved also by using let instead of var, but still, it's an example of self-executing functions :)
In the form of IIFE (or immediately invoked function expressions), they can then be used to create plugins or used as namespaces and attached to window / jquery / or other global level object for use later.
When you name a function like assigning anonymous function to a variable, you can use it later by calling the variable with parentheses, in your example, defined myFunc with
var myFunc=(function() {
console.log('Hello World');
});
Use it later in code as myFunc();
In your example, you are storing the output of function directly in variable, by calling it immediately, and there is no output to be stored.
So, if you later write console.log(myFunc);, there is undefined as output.
Better IIFE example from your code samples is the one mentioned below.
(function() {
var name="my Name"
console.log(name);
})();
It executes, does a console.log and that's it. Adds nothing to namespace or the global object in your case.
The last of your examples defines a function, does not execute it then, and since it does not have a named variable assigned, or a name, it gives syntax error and cannot be used later in code. So, below example is useless.
function() {
var name="my Name"
console.log(name);
};
You have added two more examples with var test = function myFunc. First one will work fine with test.test1(). For the second one, you need to evaluate test as a function first and then call its function, like test().test1().
I guess you miss something here. Just to make basic things clear - if you assign a self executed function to a variable the actual return value of the function when executed at this time is assigned to the variable and not the function itself.
var myFunc = (function() {
console.log('Hello World');
})();
myFunc(); // will throw error: TypeError: myFunc is not a function
myFunc === undefined
var myFunc = (function() {
console.log('Hello World');
return 'japp';
})();
myFunc(); // will throw error: TypeError: myFunc is not a function
myFunc === 'japp'
So why is this pattern around?
IIFEs are very useful to
limit the scope
if you declare
var test = 'test'; // var test actually will be assigned as a property of the current context (this)
window.test = 'test'; // so you pollute the global namespace which is not a good practice
so this would be mouch better
(function() {
var test = 'test';
})();
another very good thigs with IIFs is that you can achieve a design with "privates"
var myFunc;
(function() {
var i = 0; // i is available for myFunc with private access
myFunc = function() { console.log( ++i ) };
})();
myFunc(); // logs 1
myFunc(); // logs 2

Can someone explain the following piece of Javascript code?

I was reading another question, and I saw this:
var basketModule = (function() {
var basket = []; //private
return { //exposed to public
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
},
getTotal: function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
}());
Can you please explain why does he wrap the function in ( and )'s? Also, what is the purpose of that return? Couldn't he just write self.addItem = ... and so on?
When you wrap a function with parantheses, and add () to the end of it, it's a self executing function.
(function() x() {
//do something;
})();
And, by returning he's making basket variable somewhat private. Try getting basketModule.basket from anywhere else, and you'll get undefined.
That is called javascript Module Pattern. Defining a function and calling it immediately to prevent variables to be in the global space or to define a function name.
Note parentheses in the last line: (). The function is defined and immediately called:
(function() { })();
return { ... } returns an object having a method addItem
The intention of the code is to create an object with three methods. addItem,getItemCount and getTotal. They all depend on state represented by basket.
if basket was defined globally that state would be exposed (and there could only ever be one variable basket. both of those can lead to issues so by wrapping the entire declaration the state is encapsulated and only accessible from the created object.
There are other ways of achieving the same and the pro's and con's are related to style and how many objects of that particular type you're going to need.
wrapping the function(){}() is required since function(){}() will not parse

Calling the function immediately on the call of the page

var ObjectLiteral = {
myName:function() {
}
}
I want to call the myName function immeditetly when the page is
loaded.
I am not sure hot to write a self calling function inside an
ObjectLiteral...
You can't assign a function while simultaneously calling it (since calling it means that its return value gets assigned instead). You have to do this in two steps.
var ObjectLiteral = {
myName:function() {
}
};
ObjectLiteral.myName();
Just because no one mentioned it:
var ObjectLiteral = {
myName: function() {
console.log('myName was called!');
return arguments.callee;
}()
}
Since arguments.callee is deprecated in ES5, we would need to give the method a name:
var ObjectLiteral = {
myName: function _myName() {
console.log('myName was called!');
return _myName;
}()
}
Done. The method would get called at pageload and would still be callable later on. The caveat of doing it that way is the this context value which is replaced with window or undefined (strict) on the self-executing method. But you could apply some magic to solve that aswell. For instance, invoking .call(ObjectLiteral) in es3 or .bind(ObjectLiteral) in es5.
var ObjectLiteral = {
myName: function _myName() {
console.log('myName was called!');
return _myName;
}.call(ObjectLiteral)
}
Looks like I was wrong (damn!). The idea ok, but the assignment to ObjectLiteral is not done on the first invocation of myName. Therefore, the above code will only run from the second call on, which of course makes it useless anyway. You would need to invoke another context, but that would be just overkill.
It still does work after all, but it screws up if you need to access this, otherwise its a fine solution I think.
For your first question:
The simplest possible answer is to add this line to your script:
window.onload = ObjectLiteral.myName();
A better answer is to include that line somewhere in a larger function assigned to window.onload:
window.onload = function () {
....
ObjectLiteral.myName();
}
An even better answer is to scope things properly in case window has been reassigned.
For the second question, what to you mean by self-calling? (EDIT: n/m, Quentin answered)
Taking into account you want to execute your code after page load, jQuery is very suitable for that:
$(function() {
// called then page loaded..
var ObjectLiteral = {
myName:function() {
}
};
ObjectLiteral.myName();
});

javascript anonymous function parameter passing

I have some javascript code (within an object) :
toggle: function() {
var me = this;
var handler = function() { me.progress() };
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
I'm kind of new to javascript, so doing the above as far as I can tell actually passes the me variable into anonymous the function. I was wanting to see if there is a more declarative way to do so? I wanted something along the line of:
var handler = (function(o) { o.progress();})(this));
but that doesn't seem to be working... Am I missing something? Is this a case where "this is the way the language works so just declare a local variable and deal with it"?
UPDATE:
The source to my problem was/is my unclear understanding of scope and closures in javascript. I found this article to help me understand a little more.
You can use ".bind()":
var handler = function() { this.progress(); }.bind(this);
New browsers have "bind()", and the Mozilla docs have a solid implementation you can use to patch older browsers.
The reason
var handler = (function(o) { o.progress();})(this));
doesn't work because it just immediately calls the anon function, therefore immediately calling o.progress() and assigns the return value of the anon function (undefined) to handler. You need to return an actual function from the outer function:
handler = (function(me){
return function(){
return me.progress();
}
}(this));
On the flip side this is equivalent and just as bad looking as bad looking as the variable assignment (but can still be useful, particularly if this needs to be done in a loop, with the changing i rather than the fixed this).
BTW, if the progress function doesn't have any calls to this inside it , just doing handler = this.progress (without the parens) might suffice.
The anonymous function has access to me because it is declared inside of the outer function (the toggle function); it is closed over by the outer function.
Your handler function will be called by setInterval, which passes exactly zero arguments. This means you can't use parameters in the handler function itself.
I you really want to pass me explicitly, you could write a function accepting an parameter, and have that function return an anonymous function without parameters, but which could access the creator function's parameter:
toggle: function() {
var me = this;
var handler = (function (o) { return function() { o.progress() }; })(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
But this basically adds a layer of redirection without really making it more legible. Unless you pull that creating function outside:
function createProgressHandler(o) {
return function() {
o.progress();
};
}
// ...
toggle: function() {
var me = this;
var handler = createProgressHandler(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
What you have there is a closure. The function that is created and assigned to handler keeps a reference to the me object. This is normal, everyday JavaScript, and that's the way that closures work generally.
Have you tried to return the function like this?
var handler = function(o){
return function(){
o.progress();
}
}(me);
Now you can call:
handler();

Associative Array / Object can't be read in functions

At the very beginning of the javascript file, I have:
var lbp = {};
lbp.defaults = {
minLength: 40
};
I can successfully alert it afterwards, with:
alert(lbp.defaults.minLength);
But as soon as I put it inside a function, when I alert, I get "Undefined". What gives, and how do I avoid this? Is it absolutely necessary to pass this variable into each function, for example, by doing:
function(lbp) { alert(lbp.defaults.minLength); }
I would have thought that defining it first, it would attain global scope and not be required to be passed in?
Thanks in advance for enlightening me :)
====================================
EDIT:
The problem seems like it might be my initialize function is itself defined within lbp. Is there any way to use this function var, and still use lbp vars inside it?
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
The full bit of code looks like this:
<script type="text/javascript">
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
window.onload = lbp.initialize;
</script>
Are you actually passing lbp as the argument? Otherwise the parameter with the same name will hide the global variable.
Use this.
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(this.defaults.minLength);
};
window.onload = function() { lbp.initialize(); };
If you call initialize as a method of lbp, this will point to lbp. When you assign a function to an event handler, such as window.onload, you are essentially copying the body of that function to the object on which the event handler is defined. So,
window.onload = lbp.initialize
is the same as
window.onload = function() {
alert(this.defaults.minLength);
};
Now, this is pointing to window, which is obviously not what we want. By wrapping the call to lbp.initialize() in a function, we preserve the context of this within that function and we can make sure that it always points to lbp. Check out this for a more complete explanation.
This works for me from javascript console in Firefox:
javascript:var lbp={}; lbp.defaults={minLength: 40};function xx() { alert(lbp);alert(lbp.defaults);alert(lbp.defaults.minLength); }; xx();
Gives output [object Object], [object Object], 40.
So, it seems there might be some problem with some associated code, which is not shown?
In the original code where you are trying to use lbp in a function. You are passing lbp in as an argument. This would hide the lbp from the global scope with a local (to the function) variable of the same name (unless when calling the function you passed lbp in again).
//this is what you have and will not alert a thing other
//and will probably throw an error
function(lbp) { alert(lbp.defaults.minLength; }
//should just be this with no argument. this will allow
//the function to see lbp in the global scope.
function() { alert(lbp.defaults.minLength; }
by passing lbp as a parameter in the first function it is not seen inside the function as the global object, but the local argument.

Categories

Resources