Passing a value to anonymous function as a function argument - javascript

y1 and year1 are undefined inside the anonymous function, which is a parameter to circle.attr(). However, 'year1' does have the right value before the code enters circle.attr(). Could someone explain why this is?
**I did get the function to work by replacing the 2nd parameter with "xYear(y)"
function circleLocation(y) {
year1 = y
console.log(year1)
circle.attr('cx', function(year1) {
y1 = year1;
console.log(y1)
console.log(year1)
return xYear(y);
})
}

You are redefining year1. Arguments of a function are like variables inside their scope. So this:
function (year1) {
// ...
Is more or less the same as: (has the same effect but it's not the same thing)
function() {
var year1;
// ...
The year1 variable is shadowing the other year1 (the one you want). Try this:
circle.attr('cx', function() { // without the argument year1
y1 = year1;
console.log(y1)
console.log(year1)
return xYear(y);
})

First off, it looks like you're introducing global variables so I'd suggest using var to prevent this from happening.
var year1 = y;
Next, it's hard to understand but I think you're confused about why year1 has a value before executing your anonymous function and why it's undefined inside of the anonymous function.
The problem here is that you're shadowing the other variable. Your anonymous function takes a parameter named year1
circle.attr('cx', function(year1) {
...
That means you have declared a variable named year1 inside of that functions scope. Whenever you declare a variable inside of a scope, that declaration will shadow the previous declaration. That means, it's a whole new variable and doesn't correlate with the previous one.
var x = 2;
function useGlobal() {
// No x is declared here so it grabs the next available x value
// which is the global one
console.log(x);
}
function hideX(x) {
// Here we've said that the function takes a parameter named x
// This means we can no longer access the outer variable named x
console.log(x); // undefined
}
function declareX() {
// Same thing as before, we've declared a new x so the old
// one is shadowed
var x = 500;
console.log(x);
}
useGlobal();
hideX();
declareX();
// Notice how declareX didn't change the original x
useGlobal();

you not have introduced a parameters in function circleLocation(args)
function circleLocation(y) {
year1 = y
console.log(year1)
attr('cx', function(year1) {
y1 = year1;
console.log(y1)
console.log(year1)
return xYear(y);
})
}
function attr(n,fun){
}
circleLocation(4);

Related

Function inside a function for scoping

I am confused about this code how is this working although it looks simple but i am not getting the point of its working
<script>
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2));
console.log(add10(2));
</script>
Try to understand how closure works in JavaScript, then you will be able to understand.
Closure can simply be defined as "In JavaScript, the inner function has the access to all the variables defined outside of that functions."
Try understanding the concepts before trying to understand the code.
the function makeAdder returns a function that already will have "x" set with what ever you passed into "makeAdder"
<script>
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
//at this point "add5" looks like this:
/*
function add5(y){
return 5 + y;
}
so if we do: add5(2) - we know why we see the result we do
*/
console.log(add5(2));
</script>
It's called Closure
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
If you refer a variable in a function, it first checks that variable in its scope (inside that function) and if not found, it looks into that the environment where is was defined/declared.
So when you call your outer function with some parameter, it returns a new function. Inner function on invocation return sum of x a variable in parent scope when it (function) was defined and y the parameter passed to innner function. So inner function will keep remember the value of x when it was defined.
e.g.
var add5 = makeAdder(5);
Now add5 is a funtion which when initialized, value of x in it's parent scope was 5, so whenever you will call add5(4), it will do x + y where x = 5 value when retruned function was defined and y = 4 the value passed to add5 function or returned function.
I hope that will explain but I would suggest to read more about Javascript Closures. I added one reference above.

What is the difference between a direct argument and a global parameter, in a function?

What is the difference between a direct argument and a global, in a function?
By direct argument I mean to an argument we pass directly in function routine (instead in the subroutine based on parameters in the routine). For example:
var x = (0, 1)=>{ // Routine.
// Subroutine.
}; // Routine.
x();
By a global parameter I mean to variables defined directly in the function's routine (edit, at least in JavaScript this is formally called global parameters. For example:
var x = (x=0, y=1)=>{ // Routine.
// Subroutine.
} // Routine.
x();
How will you explain the difference between direct arguments to globals?
Sorry if something was inaccurate in terminology.
This makes no sense at all :
let x = (0, 1)=>{ // Routine.
// Subroutine.
}; // Routine.
x();
beacuse if you want to have predefined variables you just declare it in your function scope like so:
let x = () => {
const one = 1;
const two = 2;
}
A global variable is variable which you can access from anywhere in the program. In javascript you have the global object window. Global variables are in general bad practice. It would work like this:
one = 1;
two = 2;
let x = () => {
// e.g. add one and two and return
return window.one + window.two;
}
x();
Notice the that both variables declared don't have a const, let or var.
Since ES2015 you can supply default values for arguments:
let x = (x = 1, y = 2) => {
// do stuff:
}
x();
// or
x(2, 3);
In this case if you call the function without declaring the parameters within the function call it will automatically be 1 for x and 2 for y
direct arguments are not supported in javascript. Execute following code and you will see.
let x = (0, 1)=>{ // Routine.
// Subroutine.
}; // Routine.
x();

Why is non-static variable behaving like static?

function emergency() {
var ambulance = 100;
var callAmbulance = function() { alert(ambulance); }
ambulance++;
return callAmbulance;
}
var accident = emergency();
accident(); // alerts 101
I am referring to the variable 'ambulance'.
When I call accident(); it should call emergency() which should use the declared variable 'ambulance' [considering the global scope thing in javascript, still it could set the value to global] but its using old value 101 instead of setting again back to 100 - behaving more like static var.
What's the Explanation?
What you have there is called a closure. It means a function can access variables declared in outer functions (or in the global scope). It retains access even after the 'parent' function has returned. What you need to understand is that you don't get a copy. The changes performed on that variable are visible to your inner function, which in theory means you could have multiple functions sharing access to the same variable.
function f () {
var x = 0;
function a() { x += 1; }
function b() { x += 2; }
function show() { console.log(x); }
return {a:a, b:b, show:show};
}
var funcs = f();
funcs.a();
funcs.b();
funcs.show(); // 3
One thing to be aware of is that a subsequent call to f will create a new scope. This means a new x variable will be created (new a, b, show functions will be created as well).
var newFuncs = f();
newFuncs.a();
newFuncs.show(); // 1
funcs.a();
funcs.show(); // 4
So, how do you get a copy? Create a new scope.
function g () {
var x = 0;
var a;
(function (myLocal) {
a = function () { myLocal += 1; }
}(x));
x += 200;
return a;
}
JS only has pass-by-value so when you call the anonymous function, the xvariable's value will be copied into the myLocal parameter. Since a will always use the myLocal variable, not x, you can be certain that changes performed on the x variable will not affect your a function.
If, by any chance, you're coming from a PHP background you are probably used to do something like
use (&$message)
to allow modifications to be reflected in your function. In JS, this is happening by default.
You are creating a function definition which is not compiled at this time:
var callAmbulance = function() { alert(ambulance); }
And before you are sending it to the called function, you are incrementing the num:
ambulance++;
And then you are sending it to the called function:
return callAmbulance;
But whether you are sending it there or not, it doesn't matter. The below statement executes or compiles the function:
var accident = emergency();
And this takes in the current ambulance value which is 101 after the increment. This is an expected behaviour in creating function but not executing it. Please let me know, if you didn't understand this behaviour. I will explain it more clearly.

Access local variable inside a callback function

var inner = function() { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(); })(inner);
// test 2
(function(cb) { var x = 123; cb.apply(this); })(inner);
// test 3
(function(cb) { var x = 123; cb.bind(this)(); })(inner);
// test 4
(function(cb) { cb.bind({x: 123})(); })(inner);
All tests result in:
ReferenceError: x is not defined
Do someone know how it is possible to access 'x' as a local variable inside the callback?
Fact: when you do var inner = function() { console.log(x); } in your first line, x is not defined. Why? Because, inside your inner function, there's no local declaration of x (which would be done with var x = something). The runtime will then look up in the next scope, that is the global scope. There isn't, also, a declaration of x, so x is also not defined there.
The only places where there is a variable called x are inside each one of your 4 IIFEs following. But inside the IIFEs, each x is a different variable, in a different scope. So, if what you want is to console.log() the x defined inside each IIFE, you are taking the wrong approach.
Keep in mind that, when you define inner, you are capturing the environment inside the function's closure. It means that, whatever value could x have there (in the declaration of the function), would be the available value to the x variable later, when the inner function would be used. The fact that your x there is not defined is only an accessory, and is not what is causing the undesired behavior.
So, what happens is that when you call your inner function inside any of your IIFEs, the x referred to inside the inner function declaration is a captured value of what x had as a value when the function was defined, not the value that x has now in the scope where the function is currently being called. This is what is called lexical scope.
To solve this, you would have to pass the value that you want to console.log() inside the inner function as a parameter to the inner function, as so:
var inner = function(x) { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(x); })(inner);
The only way to access the local variable x in the callback, is to pass it as an argument:
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb(x); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.call(this,x); })(inner);
FURTHER
Because JS is lexically scoped, trying to reference the local variable after the anonymous function has finished executing is impossible by any other means. If you don't pass it as an argument to make it available elsewhere, JS will see it as non-reachable and it will be eligible for garbage collection.
You could redefine the callback function in the current scope:
var inner = function() { console.log(x); }
(function(cb) { var x = 123; eval('cb = ' + cb.toString()); cb(); })(inner);
// or
(function(cb) { var x = 123; eval('(' + cb.toString() + ')')(); })(inner);
This will not work if the function relies on anything in the scope in which it was originally defined or if the Javascript file has been minified. The use of eval may introduce security, performance, and code quality issues.
Have you tried using events? Emit an event inside the anonymous function, then subscribe to it in your own function somewhere else that carries out your logic.

Why is the variable inside this function global?

I thought any variable defined in a function would be local but I can easily access variable 'e' outside of its function.
function change() {
var d = 6;
e = 7;
}
change();
alert(e); //> alerts 7
Because new variables will enter the global scope by default. var prevents this from happening by constraining a variable's existence to be within the current scope.
Because it was declared without var it becomes part of the global window object.
You've not explicitly declared it as such, so it has taken global scope.
Thats because e is global by default, using var make a scope varible.
You can read more about this in Javascript Garden Scope and Namespaces
I am guessing that you are going under this assumption that
JSLint expects that a var will be
declared only once, and that it will
be declared before it is used.
Problem with your code is you are using one var, but your second line has no var in front of it. That is pushing that varaible e into the global namespace.
Why is it happening? You used a semicolon instead of a comma in the variable declaration.
function change() {
var d = 6, //Change this to a comma
e = 7;
}
change();
alert(e); //will produce an error now
It is surprisingly easy to create global variables, here are some other gotchas I've seen.
// :-( antipattern: implied global variable
function sum(x, y) {
result = x + y; // result is global
return result;
}
// :-) better
function sum(x, y) {
var result = x + y; // result is local
return result;
}
// :-( antipattern: chain assignments as part of a var declaration
function foo() {
var a = b = 0; // b is global
}
// :-) better
function foo() {
var a, b;
a = b = 0; // both local
}

Categories