problems with closure in JS - javascript

I have a problem with understanding closure when I have 3 level of scopes
https://jsfiddle.net/Ar2zee/wLy8rkyL/1/
How I can get access to parameter "g" in level3 function,
var a = 10;
function level1(b) {
var c = 1;
function level2(f) {
var d = 2;
function level3(g) {
return a + b + c + d + f + g;
}
return level3()
}
return level2;
}
var temp = level1(10);
var temp2 = temp(10);
var temp3 = temp2(10);
console.log(temp3(10)); // or level(10)(); without variable
Thank you !

Line:1 invokes level1 fn and get back fn level2 stored in alias temp.
Line:2 invokes temp fn and get back fn level3 stored in alias temp2.
Line:3 now when invoking temp2 fn you execute fn level3 getting back the result of addition operation.
So temp3 is not a function but a value.
var a = 10;
function level1(b) {
var c = 1;
function level2(f) {
var d = 2;
function level3(g) {
return a + b + c + d + f + g;
}
return level3;
}
return level2;
}
var temp = level1(10);
var temp2 = temp(10);
var temp3 = temp2(10);
console.log(temp3); // or level(10)(); without variable

Just replace
Return level3()
With
Return level3

Related

Closures: Scope Chain Variables - Not sure how variables link up

Really new to Javascript. This code is taken from MDN.
// global scope
var e = 10;
function sum(a){
return function sum2(b){
return function sum3(c){
// outer functions scope
return function sum4(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var s = sum(1);
var s1 = s(2);
var s2 = s1(3);
var s3 = s2(4);
console.log(s3) //log 20
When I try to input different variable names (EX below) they don't seem to work and I don't understand how everything links up together to spit out the answer 20.
// global scope
var e = 10;
function sum(a){
return function sum2(b){
return function sum3(c){
// outer functions scope
return function sum4(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var w = sum(1);
var x = s(2);
var y = s1(3);
var z = s2(4);
console.log(s3) //log 20
When I change it to this it also does not work. The console tells me that sa is not defined
// global scope
var e = 10;
function sm(a){
return function sa(b){
return function sb(c){
// outer functions scope
return function sc(d){
// local scope
return a + b + c + d + e;
}
}
}
}
var s = sm(1);
var s1 = sa(2);
var s2 = sb(3);
var s3 = sc(4);
console.log(sc) //log 20
I can keep throwing out more examples that don't work. Someone, please help me understand how the first example works.
function sm(a){
return function sa(b){
return function sb(c){
// outer functions scope
return function sc(d){
// local scope
return a + b + c + d + e;
}
}
}
}
The function sm is taking one argument and is returning a function which takes one argument. The function sm returns is not named sb. Try to think of it as the return value of sm .
So, when you do
var s = sm(1);
The returned function is stored in the variable s
Now if you want to run the second function (sa inside sm) you need to invoke s.
var s1 = s(2);
The returned function (sb) is stored inside varibale s1.
Similarly,
var s2 = s1(3);
var s3 = s2(4);
console.log(s3); // 20

Uncaught TypeError: test is not a function

For some reason I get an error when I give the function a name..
However if I make it an anonymous function and assign it to a variable then I can call the function.
function test(){
console.log(this)
}
test();
//**************
// recursion 1
//**************
var recursion = function(n){
if(n==0){
// console.log('yup');
return 'success';
}
// console.log(n)
return recursion(n - 1);
}
var x = recursion(10);
// console.log(x);
//**************
// recursion 2
//**************
var countDownFrom = function(x){
if(x === 0){
return true;
}
// console.log(x)
return countDownFrom(x-1)
}
// console.log(countDownFrom(10))
//**************
// fibonacci
//**************
// console.time('fib')
function fibonacci(){
var a = 0,
b = 1,
result = b;
for(var i =0; i<100; i++){
console.log(result);
result = a + b;
a=b;
b=result;
}
}
// console.log(fibonacci())
// console.timeEnd('fib')
//**************
// removeDuplicate
//**************
console.time('dups')
function removeDuplicate(arr){
var exists ={},
outArr = [],
elm;
for(var i =0; i<arr.length; i++){
elm = arr[i];
if(!exists[elm]){
console.log(exists);
outArr.push(elm);
exists[elm] = true;
console.log(exists);
console.log(outArr);
console.log(elm);
}
}
return outArr;
}
removeDuplicate([1,3,3,3,1,5,6,7,8,1]);
console.timeEnd('dups')
//**************
// mergeSorting
//**************
function mergeSortedArray(a, b){
var merged = [],
aElm = a[0],
bElm = b[0],
i = 1,
j = 1;
if(a.length ==0)
return b;
if(b.length ==0)
return a;
/*
if aElm or bElm exists we will insert to merged array
(will go inside while loop)
to insert: aElm exists and bElm doesn't exists
or both exists and aElm < bElm
this is the critical part of the example
*/
while(aElm || bElm){
if((aElm && !bElm) || aElm < bElm){
merged.push(aElm);
aElm = a[i++];
}
else {
merged.push(bElm);
bElm = b[j++];
}
}
return merged;
}
//**************
// swap number without temp
//**************
function swapNumb(a, b){
console.log('before swap: ','a: ', a, 'b: ', b);
b = b -a;
a = a+ b;
b = a-b;
console.log('after swap: ','a: ', a, 'b: ', b);
}
swapNumb(2, 3);
//**************
// JS reverse string
//**************
function reverseString(str) {
var newString = "",
stringLength = str.length;
for (var i = stringLength - 1; i >= 0; i--) {
newString += str[i];
}
return newString;
}
var newString = reverseString('hello');
console.log(newString);
var test = "yoyo";
console.log(test += 'asdfa')
//**************
// JS Reverse Word
//**************
function reverseWords(str){
var rev = [],
wordLen = 0;
for(var i = str.length-1; i>=0; i--){
if(str[i]==' ' || i==0){
rev.push(str.substr(i,wordLen+1));
wordLen = 0;
}
else
wordLen++;
}
return rev.join(' ');
}
var str = "lets go all day";
console.log(str.substr(11,5))
var s = reverseWords(str);
console.log(s);
//**************
// JS Palindrome
//**************
function isPalindrome(str){
var i, len = str.length;
for(i =0; i<len/2; i++){
if (str[i]!== str[len -1 -i])
return false;
}
return true;
}
isPalindrome('madam');
isPalindrome('toyota');
//**************
// JS this
//**************
function test(){
console.log(this)
}
test();
This might be a hoisting issue. If you have more JS code above your code snippet, test might have been assigned to something else.
This will cause a TypeError because test will be a string by the time you call it:
// ... some code
var test = 'This is a test.';
// ... more code
function test() {
console.log(this);
}
test();
This will work because test is assigned to a function right before you call it:
// ... some code
var test = 'This is a test.';
// ... more code
test = function () {
console.log(this);
}
test();
In the first example, this is what the interpreter does, more or less:
Assign a function definition to test. (This happens first because it hoists function declarations above everything else)
Reassign test to be a string.
Invoke test, which is a string.
Second example:
Declare test with no value (undefined).
Assign test to a string.
Reassign test to a function.
Invoke test, which is a function.
I just did a CTRL+F on your code and it seems that you already have a variable defined with the name of test in above scope. Please edit your code to remove the test variable declared above
It looks OK, the function prints an object when you call this inside the function
function test() {
console.log(this)
}
test()

JavaScript Closure - trying to understand following code

Coming from Java background trying to make sense out of the following code.
From:
https://medium.freecodecamp.com/lets-learn-javascript-closures-66feb44f6a44#.cbk6c4e9g
For function bar(c), which line passes argument c into bar(c) as I don't see it here.
Thanks.
var x = 10;
function foo(a) {
var b = 20;
function bar(c) {
var d = 30;
return boop(x + a + b + c + d);
}
function boop(e) {
return e * -1;
}
return bar;
}
var moar = foo(5); // Closure
/*
The function below executes the function bar which was returned
when we executed the function foo in the line above. The function bar
invokes boop, at which point bar gets suspended and boop gets push
onto the top of the call stack (see the screenshot below)
*/
moar(15);
When your first statement of function call var moar = foo(5) is executed
moar variable will be function bar(c){var d=30;return boop(x+a+b+c+d);
check the snippet for understanding
var x = 10;
function foo(a) {
var b = 20;
function bar(c) {
var d = 30;
return boop(x + a + b + c + d);
}
return bar;
}
var moor=foo(10);
console.log(moor);
2.After this statement moar(15),your are actually passing 15 to the bar method
It will execute bar method with c as 15. Now this function would return boop(80) which would just be -80
var x = 10;
function foo(a) {
var b = 20;
function bar(c) {
var d = 30;
return boop(x + a + b + c + d);
}
function boop(e) {
return e * -1;
}
return bar;
}
var moar = foo(5)
console.log(moar(15));
Hope it helps
moar(15) passes 15 into bar which gets copied into parameter c.
The // Closure comment is misleading because it is more useful to think of the closure being configured at the point of declaration of a function.
The reality is that the pointer to the outer lexical environment is configured when a function object is instantiated, and then this pointer is then copied to the execution context associated with any invocations of said function object.

Can we pass variables by reference in JavaScript Function?

I am calculating row and column of a given point by javascript function.
To achieve this I have to declare global variables
var global_row;
var global_col;
Here is function body
function calculate_city_row_col(cur_city_id)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
//Saving Result in seperate row and column
global_row = r + 1; //Global Variable
global_col = c + (cur_city_id - (max_city_id + 1)); //Global Variable
}
Here is function call
var city_id = 1244;
calculate_city_row_col(city_id);
var city_row = global_row;
var city_col = global_col;
Is there anyway to directly pass local variables? (without using global variables)
like this
calculate_city_row_col(cur_city_id, city_row_ref, city_col_ref);
Just return an object:
function calculate_city_row_col(cur_city_id)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
return {
row: r + 1,
col: c + (cur_city_id - (max_city_id + 1))
};
}
var rowAndCol = calculate_city_row_col(1244);
var city_row = rowAndCol.row;
var city_col = rowAndCol.col;
Can we pass variables by reference in JavaScript Function
No. JavaScript is purely pass-by-value (the value passed when you pass an object around is an object reference, but it's still a value).
Your options are:
Have the function return an object (or array)
function calculate_city_row_col(cur_city_id)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
//Saving Result in seperate row and column
return {
row: r + 1,
col: c + (cur_city_id - (max_city_id + 1))
};
}
Usage:
var result = calculate_city_row_col(someCityId);
console.log(result.row);
console.log(result.col);
Have the function accept a reference to an object (or array) that it updates
function calculate_city_row_col(cur_city_id, result)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
//Saving Result in seperate row and column
result.row = r + 1;
result.col = c + (cur_city_id - (max_city_id + 1));
}
Usage:
var result = {};
calculate_city_row_col(someCityId);
console.log(result.row);
console.log(result.col);
Barring a strong reason to go with #2 in a specific situation, #1 is usually the best option. For instance, if you were calling this function thousands of times in a tight loop, there might be a justification for reusing a single object (by passing it in) instead of creating a new object every time.

Should I create private variables/methods in this manner?

I am trying to learn more about how to create private variables and methods in JavaScript. The code below seems to work but I feel as though there may be a more efficient way to do this. Any suggestions?
var CountObject = (function () {
function countObject() {
// private variables
var _a = 1;
var _b = 2;
var _c = _a + _b;
// private method
addTo = function (num) {
_c = _c + _a + _b + num;
return _c;
}
}
// public method
countObject.prototype.add = function (num) {
return addTo(num);
};
return countObject;
}());
var testObject1 = new CountObject();
console.log(testObject1.add(1));
//output 7
console.log(testObject1.add(1));
//output 11
console.log(testObject1.add(1));
//output 15
var testObject2 = new CountObject();
console.log("testobject2:" + testObject2.add(100));
//output testobject2:106
addTo is not a private (local) method, but a global (not even instance-specific) function! Try to do testObject1.add(0) again after having created the testObject2 and you will see it fail.
You cannot call local (constructor-scoped) functions from the prototype, so this seems pointless. Fix it by using an instance-specific, privileged (with access to the local variables) method:
function CountObject() {
// private variables
var a = 1;
var b = 2;
var c = a + b;
// public method
this.add = function (num) {
c = c + a + b + num;
return c;
};
}

Categories