I have a function which allows user to pass a function.
function withPredicate(func){
//...
}
Inside my function, I need to detect whether the func that user pass in has closure or not.
It is not enough to get the function name and search it in window scope. User might pass in an anonymous function without closure like:
var func = function(x){return x;};
withPredicate(func);
EDIT:
I think I need to implement a function which takes a function as a argument and return bool.
function hasClosure(func){
//...
}
so several test cases are:
hasClosure(function(x){return x;}); //return false
var something = 30;
var func1 = function(x){return x.age < something;}
hasClosure(func1); //return false
var Closure = function(){
var something = 18;
var itself = function(x){
return x.age < something;
};
return itself;
};
var func2 = new Closure();
hasClosure(func2); //return true
The last one return true because func2 is not top-level function. When I see some free variable inside the function body like something, it may resolve to the variable defined in its closure other than the one defined in window.
Actually, what I need to do now is to do some manipulations based on the func that has been passed to my function. I can use JSLint to get the undeclared variable. But I also need to resolve these variables. It is acceptable that I can only resolve variables in global scope. But I still need a way to make sure that resolving these variables in global scope is correct. So I need to detect closures.
Is it possible to do that programmatically in javascript?
Alright this is really hacky and probably not worth the effort in actually writing unless your linting or something :)
Basically what you're going to have to do to determine if a function is a closure is call func.toString() which will give you the source of the function. You can then parse the function using some sort of parser which determines all the variables of the function func. You also need to determine and track how these variables are defined. In your criteria in op the criteria for it being a closure is having a variable that is defined outside of function scope and outside of window scope (thus closure scope). So if you can find any variables defined outside of these two scopes we've found a closure.
So heres the pseudocode of hasClosure(), have fun implementing.
func hasClosure(func)
source = func.toString(); //eg "function x(a) {return new Array(a)}"
variables = parseJSForVariables(source)//finds a and Array
for variable in variables:
if(variable not in window)
if(variable not defined in function)
return true //we got a closure
return false //not a closure
The correct answer highly depends on what a "closure" means in this context. The function from the question does not use the variables from the outer scope so, roughly, closure is not created for this function. But strictly speaking, closure is created for any function and binds definition context with the function. So whatever you want to detect, it requires a detailed specification.
But I can assume that the closure here means whether the function references variables declared in outer scope (just like https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures specifies). One of the static for analysis libraries can be used for this. For example, JSLint reports used but undeclared variables. Assuming that undeclared variables are just from the upper scope, this indicates that closure is created.
Related
I have somethings like:
var i = 0;
var func = function(){
console.log(i);
};
func(); //0
i++;
func(); //1
I want to have the second console also output '0',
so I change the program like:
var i = 0;
var func = (function(_i){
return function(){
console.log(_i);
};
})(i);
func(); //0
i++;
func(); //0
I know how it works, but is there any name or terms to describe such mechanism?
I've been calling this mechanism "breaking the closure" though I've had arguments in the past with people who insist on calling this technique "closure".
The reason I call it "breaking" closures is because that's what you're doing.
The classic place where you see this is in solutions for closures in loops:
var hellos = [];
for (var i=0; i < 10; i++) {
hellos.push(
(function(j){
return 'hello ' + j
})(i)
);
}
The problem is caused by a closure being created between the outer variable and references to that variable in the inner function (technically the variable is called a "free" variable rather than a closure, "closure" technically refers to the mechanism that captures the variable but in the js community we've ended up calling both things closures). So closure is the cause of the problem. Since the problem is caused by a closure being created I've started referring to the solution as "breaking the closure".
Note that even though some people call this a closure and you may google for "js closure" to read more about this technique it is ironically not a closure. What it is is simply how functions pass arguments (there's a whole side-argument about how javascript actually pass arguments to functions which you can read here: Why are objects' values captured inside function calls?). Javascript is a fairly strict pass-by-value language in the same way C is a strict pass-by-value language (C can ONLY pass by value).
When you pass a reference in js (objects, arrays) the function will not get the original reference but rather a copy of the reference. Since it is a reference it obviously points to the same object as the original reference so it is easy to mistakenly believe that javascript passes by reference. But if you try to assign a new object to the passed-in reference you will notice that the original reference does not change. For example:
function foo (x) {
x = [2,3];
}
var y = [1,2];
foo(y);
console.log(y) // prints [1,2] so foo() did not change y
It is this mechanism that is responsible for breaking the association between the outer variable (in your example that would be i) and the inner variable (_i in your example). The name of this mechanism is simply function calling (well, technically it is a subset of function calling - it is how arguments are passed to function calls).
So to recap:
I personally call it "breaking the closure"
Some people call it "closure" even though it is not a closure (the closure is what they want to avoid instead).
Side note: I realize that the original example is about a global variable but in javascript global variables are just a special case of closures - closures are ALWAYS created when you define a function, it's just that when there's no outer function the outer scope is simply the global scope.
It's called a closure. You can read more about them here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
When passing in a primitive type variable like a string or a number, the value is passed in by value. This means that any changes to that variable while in the function are completely separate from anything that happens outside the function.
if the variable in the scope is not declared, it will search the outer scope, until find it, or to the window scope. if not find, it will the variable global.
I have no idea how to describe my question .
(function(fn){
var able=123;
function tmp(){
fn()
};
tmp();
})(function(){alert(able)});
This snippet throws a Reference Error :able is not defined' .
Would you please explain how javascript get variables to me ?
The scope of the "fn" function is not the same as the "parent" function, you should pass the "able" argument when you call the fn function, and then istantiate it in the fn function itself, like this:
(function(fn){
var able=123;
function tmp(){
fn(able)
};
tmp();
})(function(able){alert(able)});
Functions create lexical closures at the time of their creation. This means that when your alert function is created, the able variable does not exist. Wrapping the execution of fn in a lexical closure that does know about able at a later moment does not affect the already created lexical closure of fn.
If you come up with a question that better explains what you are trying to do, we can propose how to properly use closures to express that idea.
java script support in function local and global scoping.
in this case the "able" is local function scope you can't access outside the function.
If you use var the variable will be declared in the local scope. If u just declare the variable without a var, it will be declared in the global scope
Your code could be rewritten like this using named functions:
var func1 = function(fn) {
var able=123;
function tmp(){
fn()
};
tmp();
}
var func2 = function() {
alert(able)
}
func1(func2);
I believe this way it is clear that the variable 'able' is defined inside 'func1' (more precisely in its local scope) and you are trying to access it inside 'func2' which is outside the scope of 'func1' so it can not "see" into this scope.
More information about scoping in JavaScript can be found here: What is the scope of variables in JavaScript?
I have read this excellent piece:
How do JavaScript closures work?
But I still have questions...
StackOverflow tags defines "Closures" as "A Closure is a first class function that refers to (closes over) variables from the scope in which it was defined. If the closure still exists after its defining scope ends, the variables it closes over will continue to exist as well".
When my functions end with a return, do all variables defined within them get deleted and memory allocation made free? It appears to me that conditions exist when one could answer yes or no.
Yes, I know memory is plentiful and free but that is not my question.
Think of an intranet based application which ajax's data back and forward during a working day. As data is received by the client, massaged, and no longer required, it can be dispensed with. Poor programming technique could result in a build up of data no longer user or required (or worse, data being used that is out of sync).
Reading the piece on closures above tells me that some variables within a function can still be referenced from outside the function scope. I am guessing that I will need to re-read the closure document several times as perhaps I've not fully understood it.
Can someone share an example on where a variable continue to exist?
And... Do I gain any benefit if, at the begining of each function I declare my variables, and prior to using a "return true;" if I reassign the variables a value of null?
All help appreciated...
num will exist within a function outside of IIFE c which returns a
var c = (function() {
var num = 10;
var a = function a(n) {
console.log(n)
return n * Math.random()
};
return a.bind(null, num)
}());
var res = [c(), c(), c()];
console.log(res)
When you return true from a function you don't have a closure. You have a closure when you return a function from a function, like this:
function makeAdder( firstNumToAdd ){
return function( secondNumToAdd ){
return mainNumToAdd + secondNumToAdd;
}
}
var add3 = makeAdder(3);
var seven = add3(4);
In the above example, the variable firstNumToAdd, although is scoped to the function makeAdder is always accessible to the inner function, even though the function exited after executing the line var add3 = makeAdder(3);
Please correct me if I am wrong, but I don't think that
some variables within a function can still be referenced from outside the function scope
is true.
Closures remember the context of a function call and bind the relevant variables (i.e. this, etc) to the closure's scope. If that is correct, then calling the closure again would cause the old variables' values to get garbage collected and you wouldn't have to worry about memory waste or out of sync data.
obj = {
func: function(){
var test = 'preserved value';
this.func2 = function(){
console.log(test);
};
}
};
obj.func();
obj.func2(); //'preserved value'
obj.func = undefined;
obj.func2(); //'preserved value'
As you can see, even after completely blowing away the original scope (func) the enclosing scope retains the test var.
var module = {};
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
function notGlobalFunction() {
console.log('I am global');
}
notGlobalFunction(); //outputs "I am global"
module.notGlobalFunction(); //outputs "I am not global"
Can anyone help me understand what's going on here? I get that if you call notGlobalFunction(), it will just call the second function.
But what is var module = {} doing? and why is it called again inside the first function?
It says this is commonly known as a self-executing anonymous function but I don't really know what that means.
Immediately invoked functions are typically used to create a local function scope that is private and cannot be accessed from the outside world and can define it's own local symbols without affecting the outside world. It's often a good practice, but in this particular case, I don't see that it creates any benefit other than a few more lines of code because it isn't used for anything.
This piece of code:
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
Would be identical to a piece of code without the immediate invocation like this:
module.notGlobalFunction = function() {
console.log('I am not global');
};
The one thing that is different is that in the first, an alias for modules called exports is created which is local to the immediately invoked function block. But, then nothing unique is done with the alias and the code could just as well have used modules directly.
The variable modules is created to be a single global parent object that can then hold many other global variables as properties. This is often called a "namespace". This is generally a good design pattern because it minimizes the number of top-level global variables that might conflict with other pieces of code used in the same project/page.
So rather than make multiple top level variables like this:
var x, y, z;
One could make a single top level variable like this:
var modules = {};
And, then attach all the other globals to it as properties:
modules.x = 5;
modules.y = 10;
modules.z = 0;
This way, while there are still multiple global variables, there is only one top-level global that might conflict with other pieces of code.
Similarly, an immediately invoked function creates a local, private scope where variables can be created that are local to that scope and cannot interfere with other pieces of code:
(function() {
var x, y, z;
// variables x, y and z are available to any code inside this immediately invoked function
// and they act like global variables inside this function block and
// there values will persist for the lifetime of the program
// But, they are not truly global and will not interfere with any other global
// variables and cannot be accessed by code outside this block.
// They create both privacy and isolation, yet work just as well
})();
Passing an argument into the immediately invoked function is just a way to pass a value into the immediately invoked function's scope that will have it's own local symbol:
(function(exports) {
// creates a local symbol in this function block called exports
// that is assigned an initial value of module
})(module);
This creates a new empty object:
var module = {};
It does the same as:
var module = new Object();
This wrapper:
(function(exports){
...
}(module));
only accomplishes to add an alias for the variable module inside the function. As there is no local variables or functions inside that anonymous function, you could do the same without it:
module.notGlobalFunction = function() {
console.log('I am not global');
};
An anonymous function like that could for example be used to create a private variable:
(function(exports){
var s = 'I am not global';
exports.notGlobalFunction = function() {
console.log(s);
};
}(module));
Now the method notGlobalFunction added to the module object can access the variable s, but no other code can reach it.
The IIFE is adding a method to the module object that is being passed in as a parameter. The code is demonstrating that functions create scope. Methods with the same name are being added to a object and the the head object (window) of the browser.
"self-executing" might be misleading. It is an anonymous function expression, that is not assigned or or given as an argument to something, but that called. Read here on Immediately-Invoked Function Expression (IIFE).
what is var module = {} doing?
It initializes an empty object that is acting as a namespace.
why is it called again inside the fist function?
It is not "called", and not "inside" the first function. The object is given as an argument ("exports") to the IEFE, and inside there is a property assigned to it.
When we have code like:
function a(){
var x =0;
this.add=function(){
alert(x++);
}
}
var test = new a();
test.add(); // alert 0
test.add(); // alert 1
test.add(); // alert 2
How does this work?
Doesn't that the value of 'x' in a() should be 'gone' as soon as test = new a() is complete? The stack contains x should also be gone as well, right? Or, does javascript always keep all the stacks ever created in case they will be referenced in future? But that wouldn't be nice, would it...?
The word you're looking for is “closure”.
Creating a function inside another function gives the inner function a (hidden) reference to the local scope in which the outer function was running.
As long as you keep a copy of your test, that has an explicit reference to the add function, and that function has an implicit reference to the scope created when calling the a constructor-function. That scope has an explicit reference to x, and any other local variables defined in the function. (That includes the this value and the constructor's arguments — though you can't access them from inside add as that function's own this/arguments are shadowing them.)
When you let go of test, the JavaScript interpreter can let go of x, because there's no way to get a reference back to that variable.
What you're seeing is the effect of a closure. The function being defined within the other function gets access to all of the variables and such in scope where it is — even after the outer function returns. More here, but basically, the variables (and arguments) in the function all exist as properties on an object (called the "variable object") related to that function call. Because the function you've bound to this.add is defined within that context, it has an enduring reference to that object, preventing the object from being garbage-collected, which means that that function can continue to access those properties (e.g., the variables and arguments to the function).
You normally hear people saying that the function closes over the x variable, but it's more complex (and interesting) than that. It's the access to the variable object that endures. This has implications. For instance:
function foo() {
var bigarray;
var x;
bigarray = /* create a massive array consuming memory */;
document.getElementById('foo').addEventListener('click', function() {
++x;
alert(x);
});
}
At first glance, we see that the click handler only ever uses x. So it only has a reference to x, right?
Wrong, the reference is to the variable object, which contains x and bigarray. So bigarray's contents will stick around as well, even though the function doesn't use them. This isn't a problem (and it's frequently useful), but it emphasizes the underlying mechanism. (And if you really don't need bigarray's contents within the click handler, you might want to do bigarray = undefined; before returning from foo just so the contents are released.)