I understand that immediate functions' closures are used to create private variables; but I am not sure of the differences, if any, between the two below patterns:
var fn = function() {
var p = param;
...
};
and
var fn = (function(p) {
...
})(param);
In both cases, p's scope is limited to fn. So why do I sometimes see the second pattern?
Thanks in advance.
The two code snippets you posted do not do the same thing.
In the first one, you are creating a variable fn which stores a reference to a function object. In the second code snippet, you are actually calling the anonymous function, and fn will store the return value.
EDIT
It seems you are unsure of the answers so I'll elaborate. Let's use an example to explain the use of each. I'm going to make up a simple function to demonstrate:
var param = 5;
var fn = function(p) {
return p * 2;
};
When this is done, you will be able to use fn to call the function. So, you could later say:
var someVar = fn(param); // someVar will be equal to 10
On the other hand, your second example:
var param = 5;
var fn = (function(p) {
return p * 2;
})(param);
fn will store the numeric value 10
NOTE
In my answer, I changed your first function to include p as an argument.
I'm not sure if I understand your question, nor if you understand what you are doing?
In your first example, you create an anonymous function, and then store it to the variable fn, but in your second example, you create an anonymous function, run it, and store the output the the variable fn. So unless you're returning p in the second example, it should not be visible at all.
You are free to correct me, if I'm wrong ;)
Related
The problem is hard to describe, so i will try my best.
I need to reverse a obfuscated javascript which is using code flow obfuscation, data transformation and some others methods.
In this code, the program is saving some functions to use them in the flow.
These functions are created by calling a specific function and i need to get arguments of this specific function by using the created function (these arguments are important to predict the stack flow)
Here is an example :
function createFunction(arg){
return function(){
'use strict';
// Do some things with arg
return true;
}
}
var func = createFunction(5);
// Need to get the argument 5 of createFunction from func var
var bool = func();
NB: The returned function is in strict mode
I don't know if it's even possible, i tried a lot of things, checked every prototype or property etc..
Thanks.
Edit :
This is not possible without editing any code, closures and lexical scoping in javascript is really strict, in my case, i just made a breakpoint after the function declaration, then i overwrited the function himself by adding prototype to the returned function with parameters.
function createFunction(arg){
var fn = function(){
'use strict';
// Do some things with arg
return true;
}
fn.prototype.arg = [arg];
return fn;
}
var func = createFunction(5);
var arg = func.prototype.arg; // 5 is here now
var bool = func();
Here is a good explanation : JS: Nested functions gain a copy of the outer function's parameters?
Also some docs : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
How to call this function in Javascript?
As it takes n as its outer function's parameter and it also needs another parameter i in its function inside, but how to call it?
function foo(n) {
return function (i) {
return n += i } }
Call the returned value of the function:
foo(1)(2);
It a classic closure example: it does return a function which has access to the n variable.
var counter = foo(0);
counter(1); // 1
counter(2); // 3
counter(5); // 8
This is a function that returns a function. Often you would want a reference to that function, Like this
foofn = foo(7);
result = foofn(7);
You could also just call the function right away
result = (foo(7))(7);
What the function does? Well that wasn't really your question...
This is the way we usually use JavaScript closures, first function creates a scope to keep the n variable safe to be used in the inner function:
var n = 11;
var myfunc = foo(n);
now you can call your myfunc function, with a simple i argument, whereas it uses n without you needing to pass it directly to your function:
myfunc(10);
so if you want to just call it, once it is created, you can do: foo(11)(10);
But in these cases we don't usually call them like this, they are usually supposed to be used as a callback or something like it.
I'm reading this page where it says:
myNameSpace = function(){
var current = null;
function init(){...}
function change(){...}
function verify(){...}
return{
init:init,
change:change
}
}();
Instead of returning the properties and methods I just return pointers
to them. This makes it easy to call functions and access variables
from other places without having to go through the myNameSpace name.
But I don't see how that's true. You still have to do myNameSpace.init() to call init. init() alone doesn't work.
Edit: it occurred to me later that maybe the author meant they were able to call init() without qualification inside the anonymous function. But what stumped me is that the author's previous examples were already able to do that. Specifically, in the immediately foregoing example:
myNameSpace = function(){
var current = null;
function verify(){...}
return{
init:function(){...}
change:function(){...}
}
}();
s/he defined init as s/he was returning it, instead of the example above where s/he defined init first then returned a pointer to it. But in that earlier example, within the anonymous function, if you wanted to call init() without having to do myNameSpace.init(), you already can. So how is the quoted example better?.
Can someone explain? Thanks.
The idea of using a function to clean up scope is, let's say you have a program that looks like this:
var number = 10;
var multiplier = 2;
var endingText = " days left!";
var string = (10 * 2) + endingText;
// string is "20 days left!"
This is an extremely contrived example, but hopefully it's obvious enough that this will declare four variables in the global scope, which is horrible. Let's say what you really want is string, but you still want to keep the other three variables around for whatever reason. You can put them inside an anonymous function, like so:
var string;
(function(){
var number = 10;
var multiplier = 2;
var endingText = " days left!";
string = (10 * 2) + endingText;
})();
// string is still "20 days left!"
Because variables are function scoped, number, multiplier and endingText are NOT declared in the global scope. However, you are still able to use them to get the result that you wanted in the first place.
By the way, you need to wrap parens around a function if you want to immediately invoke it. Also, you should not confuse this with namespacing. Namespacing in JavaScript is the idea of assigning meaningful values to the properties of objects.
var foo = {
hello: "goodbye",
frank: "bob"
};
hello and frank are declared in the foo namespace. That's all there is to it. The example that you posted uses both the namespacing concept and immediately invoking function concept to clean up variables.
The wording is a bit confusing. He meant to say:
Functions and variables can now be easily accessed without a namespace from inside the module
- in contrast to the object literal pattern or the previous example where he put the public methods directly on the exported object. Of course, from outside you always will need to access them as properties of the namespace object - that's the whole point of making it a namespace :-)
For an example, let's fill the functions with a some minimal code:
myNameSpace = function(){
var current = null;
function verify(…){…}
return {
init:function(el){
el.addEventListener("input", myNameSpace.change, false);
// ^^^^^^^^^^^^^^^^^^
},
change:function(){
if (!verify(this.value)) alert("wrong");
}
}
}();
myNameSpace.init(document.getElementById("testInput"));
vs
myNameSpace = function(){
var current = null;
function verify(…){…}
function change(){
if (!verify(this.value)) alert("wrong");
}
function init(el){
el.addEventListener("input", change, false);
// ^^^^^^
}
return {
init:init,
change:change
}
}();
myNameSpace.init(document.getElementById("testInput")); // no difference here
The differences may be minimal in this example, but when you have lots of functions mutually referencing each other it can matter. Also, you would know that all local, namespace-less functions belong to the current module, which massively increases maintainability when dealing with many different namespaces.
I'm starting learning javascript for a project, I've found a script that does a part of what I need to do, I'd like to know how it works, both for me and in case it needs to be modified.
Originally it was used inside the page, now I've put it in a file on its own and does not work anymore, so I'm dividing it in parts, because I fail to get the whole thing.
Here is what bother me most for now:
1) Is this a declaration of a function? What is its name? How can it be invoked?
(function() {
//some code
})();
2) No clue of what is going on here
var VARIABLE = VARIABLE || {};
3) Am I defining the implementation of methodCall here? Something like overriding a method in Java?
VARIABLE.methodCall = function(parameter) {
console.log("parameter was: " + parameter);
};
Thank you in advance for your help.
1) creates an unnamed function and executes it. this is useful for creating a scope for local variables that are invisible outside the function. You don't need to invoke it aside from this, the '()' at the end does that for you.
2) if variable is null/undefined, set it to an empty object.
3) yes, that should work as you expect, you can call VARIABLE.methodCall(parameter)
in response to your comment, here is a common example
function foo (VARIABLE) {
var VARIABLE = VARIABLE || {};
}
(function() {
//some code
})();
simply runs //some code, but variables in it will not remain, since the function() { } block introduces a new inner scope.
function() { } notation is called a closure, it allows variables be functions. For example,
(function() { })() is a common JavaScript idiom. After the ), there is (), which invokes the expression before as function, so (callback || function(x) { return x; })(x) is allowed.
var a = function a() { return 1; }
var VARIABLE = VARIABLE || {}; uses the short-circuit OR, If VARIABLE is not defined, VARIABLE will be set to {}, an empty object. (otherwise, if VARIABLE exists, it will not change)
x = A || B means "If A evaluates to TRUE, x is A, otherwise, x is B.".
VARIABLE.methodCall, as you said, adds methodCall to VARIABLE, without erasing other values in VARIABLE
When I pass 'this' to an anonymous function like so:
MyClass.prototype.trigger = function(){
window.setTimeout(function(){this.onTimeout();},1000);
}
I get a "this.onTimeout is not a function"-error. I guess that 'this' is no longer available at the time the anonymous function is executing? So I've been doing this:
MyClass.prototype.trigger = function(){
var me = this
window.setTimeout(function(){me.onTimeout();},1000);
}
Is this really how you're supposed to do things? It kinda works, but it feels weird.
Then we have this example:
$(function(){
function MyClass(){
this.queue = new Array();
}
MyClass.prototype.gotAnswer = function(count){
$('body').append("count:"+count+"<br/>");
}
MyClass.prototype.loadAll = function(){
var count = 0;
var item;
while(item = this.queue.pop()){
count++;
var me = this;
$.getJSON("answer.html",{},function(data){me.gotAnswer(count);});
}
}
var o = new MyClass();
o.queue.push(1);
o.queue.push(2);
o.loadAll();
});
This outputs:
2
2
Shouldn't it output:
1
2
instead? Then I discovered that putting the $.getJSON-statement in another function makes it all work:
MyClass.prototype.loadAll = function(){
var count = 0;
var item;
while(item = this.queue.pop()){
count++;
this.newRequest(count);
}
}
MyClass.prototype.newRequest = function(count){
var me = this;
$.getJSON("answer.html",null,function(data){ me.gotAnswer(count); });
}
This outputs:
1
2
(Or the other way around.) What's happening here? What is the right way to pass variables to an anonnymous function?
Sorry for the confusing and lengthy post.
What you are experiencing is the correct behavior - it's not a good behavior, but it's part of the language. The value of "this" is reset inside every function definition. There are four ways to call a function that have different ways of setting "this".
The regular function invocation myFunc(param1, param2); This way of calling a function will always reset "this" to the global object. That's what's happening in your case.
Calling it as a method myObj.myFunc(param1, param2); This unsurprisingly sets "this" to whatever object the method is being called on. Here, "this" == "myObj".
Apply method invocation myFunc.apply(myObj, [param1, param2]) This is an interesting one - here "this" is set to the object you pass as the first parameter to the apply method - it's like calling a method on an object that does not have that method (be careful that the function is written to be called this way). All functions by default have the apply method.
As a constructor (with "new") myNewObj = new MyConstructor(param1, param2); When you call a function this way, "this" is initialized to a new object that inherits methods and properties from your function's prototype property. In this case, the new object would inherit from MyConstructor.prototype. In addition, if you don't return a value explicitly, "this" will be returned.
The solution you used is the recommended solution - assign the outside value of "this" to another variable that will still be visible inside your function. The only thing I would change is to call the variable "that" as Török Gábor says - that's sort of the de-facto standard and might make your code easier to read for other programmers.
You are confused about the closures.
For the first problem, yes, you are right, that is the way it can be done. The only difference that there is a convention to name the variable that that holds this.
MyClass.prototype.trigger = function(){
var that = this;
window.setTimeout(function(){that.onTimeout();},1000);
}
There is already a nice thread about this on StackOverflow. Check answers for question
How does a javascript closure work?.
Your second problem is an exact duplicate of Javascript closure inside loops - simple practical example.
you will have the same problem if inside your new method: newRequest you have to use a "for" or a "while" statement.
Another solution could be creating a closure:
like that:
$.getJSON("answer.html",{},(function(me){return function(data){me.gotAnswer(count);}})(this));