This question already has answers here:
var functionName = function() {} vs function functionName() {}
(41 answers)
Javascript named function as an expression
(1 answer)
Closed 8 years ago.
I'm following John Resig's Secrets of JS ninja slides and I've found something I don't clearly understand. Following code defines a named function expression:
var ninja = function myNinja(){
console.log(myNinja); // function myNinja() {...}
};
myNinja; // undefined
As I can see, in the current scope (suppose it's global), ninja is the variable that holds reference to the named function myNinja. ninja variable is accessible in the scope - that's clear, but myNinja is not accessible in the scope (but it's accessible inside its own function). How come?
If I define a function (not using a function expression, but function declaration):
function Cheese() {
console.log(Cheese);
}
then it's accessible in the current scope. I know that this just works like that - but can someone explain why is that?
In his book, The Secrets of the JavaScript Ninja, John Resig makes a wonderful explanation about this concept.
http://jsninja.com/
Below are the quotes from the book:
4.2.4. Inline named functions
<script type="text/javascript">
var ninja = function myNinja(){
assert(ninja == myNinja, "this is named two things at once!");
};
ninja();
assert(typeof myNinja == "undefined",
"But myNinja isn't defined outside of the function.");
</script>
This listing brings up the most important point regarding inline
functions: even though inline functions can be named, those names are
only visible within the functions themselves.
Remember the scoping rules we talked about back in chapter 3? Inline
function names act somewhat like variable names, and their scope is
limited to the function within which they’re declared.
3.2.1. Scoping and functions
Variable declarations are in scope from their point of declaration to
the end of the function within which they’re declared, regardless of
block nesting.
If you would like to know more about this concept, this book will help you.
why is that?
A function expression creates a new function object every time it is evaluated. What happens with that result is irrelevant at first. But…
var ninja;
// myNinja; - what would you expect it to be here?
for (var i=0; i<5; i++)
ninja = function myNinja(){
console.log(myNinja);
};
// myNinja; - *which one* would you expect it to be here?
ninja();
The call to ninja() is obvious, it references the function that was assigned to that variable at last. And the myNinja in the console.log references the current function object - it's in its own scope.
But the myNinja identifier would be ambiguous outside the function itself.
In contrast, a function declaration is hoisted and accessible from the whole scope. Its identifier uniquely refers to the single function object which is created once in the initialisation of the scope.
Imagine that when you simply define a function (cheese), you tell the current scope - "I want you to know this function, it's name is cheese.
when you use the var ninja, you're dealing the ninja scope now, telling it basically the same thing. so now you new function (myNinja) is know only at the current (ninja) scope...
Name is a property of the function object. If you were to inspect a Function instance in the debugger, you will see a name property on it. In the case of functions that are defined in the global scope, the value of name is automatically used as the name of the property of the
window object by which it is referenced.
In the case of an inline function, you are defining the name of the property by which the function will be referenced. The JS engine does not need to use the name property from the Function instance.
Related
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 am going through the book JavaScript: The Complete Reference, Third Edition By: Thomas Powell; Fritz Schneider to have a detailed understanding of the concepts.
Scoping Rules
Outside of a function or object, variables are within the global space whether explicitly defined with var or not. Within a function or object, if the var statement is used, the defined variable will be local to the construct; without the statement, it will be global.
Commonly, JavaScript developers make assumptions about scoping rules with var that aren’t quite true. For example, a var statement found within a for loop does not scope that value to the loop. In this case, it is scoped to either the function it is within or to the global space if it is outside a function or an object.
Just to see what happens consequently, I coded like this,
When I press Ctrl+Space in Eclipse IDE for it to show JavaScript proposals, why am I able to access the variable jLocal outside the function?
As per the author description:
For example, a var statement found within a for loop does not scope that value to the loop. In this case, it is scoped to either the function it is within or to the global space if it is outside a function or an object.
Because at the bottom of your code you have:
...
jLocal = jLocal + j; // defined not in any functions
...
Making it global, but not necessary defined.
It isn't the case of a local function. myFunc is global, just as the variable jLocal is (albeit the name). Because of hoisting, jLocal is assumed to be declared on top of parent scope.
Looking more carefully, there's two variable's named jLocal. One local to myFunc and an implicit one on global scope.
Want a tip?
Put "use strict"; just before var global1 = true;. An HTML 5 implementation would be able to catch and show your error.
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.
When using Javascript Closures, is there some difference in using Object literal Vs Constructor based objects ?
Are there just syntax difference OR is there some other difference as well for Closures?
Any example explaining the 2 differences would be really helpful.
Closures are a feature of functional programming. They have nothing to do with objects or object literals.
Read the following answer - it explains closures really well: https://stackoverflow.com/a/12931785/783743
In general a closure is a function which closes over the variables in a nested function which moves out of the scope of the closure. For example:
function getCounter() {
var count = 0;
return function counter() {
return ++count;
};
}
var counter = getCounter();
counter(); // 1
counter(); // 2
counter(); // 3
Here the function getCounter becomes a closure because it closes over the variable count used in the nested function counter when the nested function is returned (moves out of the scope of getCounter).
The variable which is closed over (in this case count) is called an upvalue. Closures are important because they allow values which would otherwise go out of scope (be garbage collected) to remain alive. This is not possible in languages like C/C++ and Java.
Closure is more about the function scope of the variable. So the important thing to know is that the scope of a variable is the function it was defined in. Any function that run inside this scope will have access to its parent function per se. Parent function won't have access to a child function variable, because it's outside of that child's scope.
Therefore a variable in an object literal, would be scoped to the function that it is contained it. (If it's not in a function, then it's in the global scope). A constructor is a function so any variables that it defines, is scoped in itself and inaccessible outside. Any inner methods that are in the constructor has access to those defined variables.
Closures are created when a function has access to a variable that is outside its own scope and that variable may be changed or altered by something else...even well after the function has finished execution.
I hope that helped some what.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
Function declaration - Function Expression - Scope
I've learned about var a = 1, is defining a local variable, but talk about function, I thought It's only available within the current scope as the var variable behave, what's the difference between the following two code snippet?
function aPrint() {
console.log('a');
}
var a = function aPrent() {
console.log('a');
}
Your first example is a "function declaration". It declares a function that will be available anywhere in the scope in which it is declared (so you can call it before it appears in the source code). This is sometimes known as "hoisting" (as in, it gets hoisted to the top of its scope).
Your second example is a "named function expression". The variable declaration is hoisted to the top of the scope in which it is defined (like a function declaration) but the assignment still happens where you expect it to, so you can't call the function until after it has been assigned to the variable.
There is a third option, which is just a "function expression", where the function does not have a name (it's an anonymous function):
var a = function() {
console.log('a');
}
You will probably find that you have little use for named function expressions (although it can be useful when debugging), so it's usually better to use the anonymous function. In a named function expression, the name is only in scope inside the function itself, so you can't refer to the function by name normally.
here is a best article that may help you.
refer http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
function aPrint() {}
Declares a function (but does not execute it).
It will usually have some code between the curly brackets.
var a = aPrint()
Declares a variable, invokes a function (aPrint) and sets the value of aPrint to the return of the function.
var a= new aPrint()
Creates a new instance of an object based on the aPrint function. So the variable is now an Object, not just a string or a number.
Objects can contain indexed strings, numbers and even functions, and you can add more stuff to them, they're pretty awesome. The whole concept of Object Oriented Programming (OOP) is based on this.