I'm trying to run the same function multiple times at once but if I create a local one with var variablename the sub-functions dont recognize it. And if I make it global, all instances of the Function will overwrite it.
function vladimir(){
var test="hello";
hanspeter();
}
function hanspeter(){
console.log(test);
}
console.log outputs undefined.
You're running into a scoping issue here.
When you declare methods without using var (function <function_name>() {}), those function declarations are moved to the top of the local scope (called function hoisting, if you want to look it up).
If you manually declare you functions, you have to wait until they are both declared before you can use them. This is because the first function won't know about any functions declared under it.
You've also got an issue where variables aren't being scoped. If you have a variable that you declare in one function, it isn't guaranteed to be there in another (since it is a different scope).
If you want to pass these variables around, the easiest way is to pass these into the function parameters, which will be reachable in your other function.
So in your simple example, you could get it to work like this:
var hanspeter = function (test) {
console.log(test);
}
var vladimir = function() {
hanspeter( "hello" );
}
Use function arguments:
function vladimir(){
var test="hello";
hanspeter(test);
}
function hanspeter(arg){
console.log(arg);
}
https://learn.jquery.com/javascript-101/functions/
JavaScript uses lexical scoping - it looks like you're expecting dynamic scoping. Essentially what this means is that a function has access to variables based on where it is declared, not where it is called. For example, the following would work:
function vladimir(){
var test="hello";
function hanspeter(){
console.log(test);
}
hanspeter();
}
Because test exists where hanspeter is declared. But in yours, test exists where hanspeter is called, which does not give it access.
You can also get variables by passing them:
function vladimir(){
var test="hello";
hanspeter(test);
}
function hanspeter(test2){
console.log(test2);
}
I called the argument to hanspeter test2 to show that it is the argument's name that matters, not the name of the variable being passed.
Related
I initialized a variable of function through "." outside the function. Regarding closure rule, it should be set inside the function scope and after execution should be gone. But
Why after calling the function variable still exists?
Why can I access inside a function only through "."?
I initialized variable outside of the function through "." like f1.a = "any variable".
I checked if the variable of function initialized outside is accessible inside a function without ".":
I tried to get access to the variable inside the function. It seems if I get access to the variable by itself without "." it gives me an error "variable is not defined".
I checked if the variable of function initialized outside will be gone after function execution:
I call function and check if the value of the variable after execution is still available. Yes, it was still there.
f1.a = "any variable";
function f1(){
(function()
{
console.log(a);
}()) // a is not defined
}
f1();
console.log(f1.a); // after f1(), f1.a still exist
I expected variable "a" visible by itself inside the "f1" since I initialized inside the function scope f1.a = "any variable", but I can get access only with "."
I expected variable "a" will be gone after execution f1(), but it still exists
There are several things you need to understand to get a clear idea of what's happening here. First, JavaScript hoists function definitions to the top of the file.
Knowing that, you could imagine your code is something like this once JavaScript interprets it:
var f1 = function (){
(function()
{
console.log(a);
}()) // a is not defined
}
f1.a = "any variable"
f1();
console.log(f1.a);
Secondly, in your first console.log(a) you are referencing a variable a which was never declared. If you change that to console.log(f1.a) you'll see the value of f1.a as expected.
It's also not clear why you are using an immediately invoked function inside of your f1 function. It makes analyzing this code even more complex. It seems like you are trying to get a better understanding of how closures work? But for closures you should be interested in variables declared inside of f1, rather than properties of f1. For example, something like this.
f1 = function (){
var a = 'something'
return function()
{
console.log(a);
}
}
var closure = f1();
// f1 is finished running here.
closure(); // closure still has access to f1's variable.
I think the three areas you could learn more about to understand the code above are 1. Scope and especially hoisting 2. Objects, this and object properties and 3. Closures.
function test() {
var str = 'adarsh';
// f1(); - This gives an error.
$('body').click(function f1() {
console.log(str);
});
}
test();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I want to know why the above snippet gives an error when I try to access f1() inside the function test.
What is the function f1 scoped to?
I know it is not the window because I cannot access window.f1 after executing the above snippet.
Note: I know I can declare function f1 first and then pass the reference to it in the click function. However I want to know what is the point of naming 'anonymous' functions in such contexts if we cannot access them anywhere through that name.
A function declaration will:
Create a variable with the same name as the function in the current scope.
A named function expression (which is what you have here) will:
Create a variable with the same name as the function inside the scope of that function (which is useful for calling itself recursively).
Evaluate as the function
So there are two ways you can access the function you created with the named function expression:
Put something on the left hand side of the expression. In this case you are already doing that by passing it to click(), so the click function can do something with it
Call it by name from inside itself
There are no further references to it in the scope of test.
However I want to know what is the point of naming 'anonymous' functions in such contexts if we cannot access them anywhere through that name.
As I said, the variable is useful for calling it recursively.
The name (which is different to the variable) is also useful as it shows up in debuggers. It is a lot easier to deal with a stacktrace consisting of a dozen useful names than one which is just a dozen repetitions of (anonymous function).
The BindingIdentifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the BindingIdentifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression. ## http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-runtime-semantics-evaluation
In other words, when you have a function expression like function someName() {...} (not to confuse with a function declaration) the name is bound inside the function, not in the containing scope.
fun = function someName() {
alert(someName); // works
};
alert(typeof someName); // doesn't work
fun();
The purpose of giving names to function expressions is to have meaningful stack traces.
What is the function 'f1' scoped to?
It's not scoped to anything. The reference of the function is provided to the handler only, so there is nothing else defined which points to that function. If you want to define the function so that it can be called in multiple places you would need to change your logic to something like this:
function test() {
var str = 'adarsh';
$('body').click(function() { // < note the anonymous function here
f1(str);
});
}
function f1(str) {
console.log(str);
}
test();
f1('foo bar');
Calling a function passed to a JQuery handler
You can use jQuery._data() to access and call the event handler of click, f1, outside of .click()
function test() {
var str = "adarsh";
// f1(); - This gives an error.
$("body").click(function f1() {
console.log(str);
});
var ref = $._data(document.body, "events")["click"][0];
console.log(ref.handler, ref.handler.name);
ref.handler()
}
test();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>click</body>
I thought I understood variable scope, but seems like I still need to learn some more.
I have a setup like this:
function start() {
var playerLocation = world001map;
var doggy = 'wooof!';
function loadLevel(levelToLoad) {
levelToLoad();
loadLevel(playerLocation);
}
}
function world001map() {
alert(doggy);
}
It seems like I can't access the doggy variable from the world001map function. I thought child functions could always access the variables of their parents.
Why can't I access "doggy" from "world001map" and is there some way to fix the situation?
Scope is determined by where a function is defined (i.e. the position in the code of the function declaration or function expression), not where it is copied to.
var playerLocation = world001map does not give world001map access to variables that are scoped to start
yes, doggy is isolated to the start scope.
two ways to fix: pass doggy to world001map:
function world001map(doggy)
2, make doggy global, set it up outside the start function.
I am doing a small work in JavaScript and I want to avoid problems, so I am asking beforehand.
Can I use two different variables and name them the same in different functions, given that one of these functions calls the other?
So, when I define the variable in the second function, will it interpret as two different variables, or will it rewrite the value of the original variable from the first function? (Or, will it throw an error due to the fact that a variable with that name already exists?)
Here is an example:
function first()
{
var a = somevalue;
second();
}
function second()
{
var a = differentvalue;
}
Thanks!
Variables declared inside a function are local to that function, and doesn't conflict with variables with the same name anywhere else.
You can even have a global variable with the same name, and the code inside the function will only see the local variable.
Example:
var a; // global variable
function first() {
var a; // local variable in first
second();
}
function second() {
var a; // local variable in second
}
(Global variables should of course be used as little as possible, but it's good to know that you can have a local variable that is unaffected by any global variables that may exist.)
A local variable inside a function is not only local to the function, it's actually local to that execution of the function. If you call the function again, a new variable is created, and if the function calls itself (recursion), each level will have it's own variable.
Yes you can, as long as you don't forget the var keyword : the scope of a variable is either the function in which it is declared or the global scope. There is no way from outside the functions to gain access to the variables they declare.
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.