Is This Callback Referencing a Dereferenced Closure? - javascript

I have been dealing with issues in multiple pieces of code but it seems to boil down to what I’m showing in this demo. I think it is related to the ’s dereferencing of a closure:
function get_5(callback) {
var result = 5;
callback(result);
}
function get_self(x) {
return x;
}
get_5(console.log);
// 5
console.log(get_self(5));
// 5
In the first result, the first function ran as expected, sending its hidden variable into the input of the console.log function.
The second result also makes sense, as it really just proves the second function works: it takes what was fed in and returns it.
But things get strange when I try to combine the two functions:
var a = get_5(get_self);
console.log(a);
// Undefined!
This third result is undefined, strangely enough, and I am not sure why. Is the closure being dereferenced, maybe to the “sneakiness” of the get_self function? How can I fix this? As a bonus, is there a way to eliminate the get_self function entirely and be able to directly read the variable result, which isn’t modified, without specifying any particular callback?

get_5 has no return statement. It doesn't matter what you pass to get_5, it will always return undefined.
Perl will return the result of evaluating the last statement in a sub, but JavaScript will not.
If you want get_5 to return the result of calling the callback you pass to it, then you have to say so explicitly:
function get_5(callback) {
var result = 5;
return callback(result);
}

Related

The step by step actions which occur as a result of the return operator, inside a function

I am new learning the fundamentals. I have looked at many questions on here and youtube, and even on my udemy lecture. But none answer my question.
To be clear, my question is NOT how to use the return operator. I can use it perfectly well. The question is more to do with HOW it works, and what is actually happening in detail.
And please don't say "So in short, when we return something from a function, we are actually returning it from a function." - because this was one of the explainations I got before, and it does not explain anything to me hahaha :)
Here is the example code for this question:
function example(digit1, digit2) {
const sum = digit1 + digit2;
return `${sum}`
}
const invoke = example(1, 2);
console.log(invoke);
I think the best way to answer this question is to give me a step by step list of the journey that 'sum' makes. From the moment it is written, to the end of the whole code.
The return operator is clearly moving 'sum', as the word 'return' can only mean this, by definition.
When I read this code I see that 'sum' is inside the curly braces off the function, and then directly after this 'sum' is then RETURNED (to the place which it started). Now as 'sum' has not gone anywhere, returning it (to the place which it started) is REDUNDANT.
when the function is invoked there must be some kind of journey happening which I do not understand.
Thank you for your time :)
When I read this code I see that 'sum' is inside the curly braces off the function, and then directly after this 'sum' is then RETURNED (to the place which it started). Now as 'sum' has not gone anywhere, returning it (to the place which it started) is REDUNDANT.
Nope. You're misinterpreting what's "returning" and where it's being returned to.
The function is returning the value contained in sum to whatever called the function, not to "the place where it (sum) started".
function example(digit1, digit2) {
const sum = digit1 + digit2;
return `${sum}`
}
const invoke = example(1, 2);
console.log(invoke);
The function example receives two values which it places in the variables digit1 and digit2, then creates a new variable sum which contains the result of adding digit1 and digit2. (The variables digit1, digit2, and sum are all scoped to the function itself; they do not exist outside of that function.) It then returns the value contained in sum -- not the variable itself -- to the thing that called the function.
Which in this case, is this line:
const invoke = example(1, 2)
The function example receives the values 1 and 2, and returns the value "3". Which means that outside the function, the returned value takes the place of the function call itself, resulting in, effectively,
const invoke = "3"
The code outside the function "calls" the function. The function "returns" a value -- not a variable, a value! -- to the code outside the function. You can think of a function as a box with inputs and an output: you call it with inputs, and it returns to you an output value.
(Incidentally, the return statement you've used unnecessarily coerces the result into a string, where you probably want a number: just return sum would likely be preferable.)
return will put whats being returned (sum in this case) at the place where the function is invoked (in this case, in front of invoke).
so invoke = sum (sum is returned/ put on the place where the function is invoked)

Is it good practice to override function parameter value?

In JavaScript consider I am trying to append a new value and return it.
I have below example regarding overriding parameter value
The below function receives a string value as param and overriding the param with new value and returning it.
function test(value) {
value = value + "hi";
return value;
}
console.log(test("Hello"));
The below function receives a string value as param. I would like to append a new value and return it. So I assigned value to a local variable and then appended strong to a new variable and returning it.
function test(value) {
let temp = value;
temp = value + "hi";
return temp;
}
console.log(test("Hello"));
I am calling it and passing value
test(“Hello”);
Which one is recommended from above?
It's purely a matter of style. Some people think you should leave parameter values alone, others think it's fine to change them.¹
From a practical perspective, it doesn't cause any harm. That is, there is no hidden side-effect to doing so. In particular, since JavaScript is purely pass-by-value, reassigning the parameter can't have any effect on whatever argument was used to fill in that parameter:
function test(value) {
value = value + "hi";
return value;
}
let a = "let's say ";
let b = test(a);
console.log(b); // "let's say hi"
console.log(a === b); // false, `a` was not modified
Your version with temp can be simpler, though:
function test(value) {
let temp = value + "hi";
return temp;
}
(or even
function test(value) {
return value + "hi";
}
but I figure it's highly simplified for the question.)
¹ (I happen to be in the latter camp, but that's neither here nor there.)
Yes, this is not at all wrong and is often done by many programmers across many languages. It is a common practice.
You can use it in cases where you want to use the parameter value inside the function but after making certain modifications to it.
For example, I might want to add two numbers using a function add(a, b) where a and b can be strings or integers or floats.
But just to be sure about it, I can define the add function in the following way:
function add(a,b) {
a = parseFloat(a);
b = parseFloat(b);
return a + b;
}
and this is perfectly fine. This way I can be always sure that there will be no exceptions thrown or in case parameters were passed as strings, it doesn't returns 12 (if I said add(1,2)) when really it should have been 3.
By making parameter overriding a common practice and incorporating it into your coding style, you spare the browser from creating or defining new variables just to modify those variable values. This might not mean much in small applications, but in large scale heavy applications, it might make a noticeable difference especially on low end devices.
The short answer is: it's only a matter of style.
However, this isn't always right. When passing objects, they will be passed by reference, meaning that every change you'll make to the parameter will affect the original object:
const obj = {originalValue: true};
function modifyObject(input) {
input.originalValue = false; // The change happens here
return input; // So it will take place regardless of this line
}
console.log('before:', obj);
modifyObject(obj); // See? we don't even retrieve the return value
console.log('after:', obj);
If we were talking about Java, then creating a new variable would be good practice. As there is something called the Garbage Collector that collects unused variables, etc. and discards them. So keeping a link to the original variable wouldn't allow the collector to discard the variable. (I read this somewhere, but some people said to me it doesn't really work this way, so read more about this online if you want)
In JavaScript, however, it doesn't really matter. It depends on you. Your style. It also depends on the situation as it can be useful sometimes. But really it doesn't really matter. Do as you like.
If you want to simplify it you can do as #T.JCrowder said:
function test(value){
return value+ “hi”;
}
That's about it.
Using ES6 Template literals
function test(value){
return `${value} hi`;
}

Function with sub-functions but also its own... function...?

Please: only pure vanilla JS code. No jQuery or other external things, thank you. :)
How can I create a function that contains sub-functions but also returns a value if no sub-function is called?
For example, let's take a number variable num.
I want to add a round() function to the number variable; if it's called directly, I want it to round up or down depending on the variable's actual value.
var num=4.12;
num.prototype.round=function(){return Math.round(this);}
Now I wand round() to have sub-functions that will round up or down, disregarding the decimal values.
num.prototype.round.up=function(){return Math.ceil(this);}
num.prototype.round.down=function(){return Math.floor(this);}
If I do that and log num.round() to console, it does what it's supposed to. But if I log num.round.up() to console, I get an error telling me that num.round.up() is not a function.
So I try putting the sub-functions into the main function declaration like this:
num.prototype.round=function(){
var n=this;
this.up=function(){return Math.ceil(n);}
this.prototype.round.down=function(){return Math.floor(n);}
return Math.round(n);
}
Then again, num.round() will return the correctly rounded value, but both num.round.up() and num.round.down() will return "not a function" errors.
I'm going nuts trying to figure this out... I didn't only try what I mentioned above, but I also tried doing this with immediately executing functions like this:
num.round=(function(){
return function(){
var that=this;
/* anything in here is already useless because this
is no longer num's value but [Object window]... */
}
})();
I guess part of the trouble is that I'm so weak at OOP that I just have no clue about the correct terminology... naturally, that doesn't help when searching for clues or when it comes to knowing any potential reasons why something like this should not work...
So is there any way at all to do this?
Well you can pass a parameter to the function. Not the exact implementation you want, just an alternative:
var num = function (defaultNumValue) {
var delegation = {
'up': 'ceil',
'down': 'floor'
};
return {
round: function (val) {
return Math[ delegation[val] || 'round' ](defaultNumValue);
}
}
};
var sth = num(1.5);
sth.round(); // 2
sth.round('up'); // 2
sth.round('down'); // 1
May be something like:
function num(n) {
this.num=n;
this.round=Math.round(n);
this.up=Math.ceil(n);
this.down=Math.floor(n);
this.up2=function(){return Math.ceil(n);}
}
var num = new num(4.12);
alert(num.num);
alert(num.round);
alert(num.up);
alert(num.down);
alert(num.up2());

Return statement in javascript doesn't exit the function?

I wrote a simple function to sort objects not expecting it to work but it does:
function sortObjs(objArr,field) {
objArr.sort(
function(a,b) {
if( isNaN(a[field]) ) {
return a[field].localeCompare(b[field]);
} else {
return parseFloat(a[field]) - parseFloat(b[field])
}
}
);
return objArr;
}
When I call this function I get my sorted objects without issue. But I was not expecting it to work because I thought the first two return statements would exit the function before it got to the last statement: return objArr.
You have a nested function. The first two returns will exit the inner function, while the last one will exit the outer one.
EDIT:
You can think of function returns as "replacing" the function with the returned value. For example:
var i = getSum(1, 3);
function getSum(a, b) {
return a + b;
}
The function getSum returns the sum of a and b. The line var i = getSum(1, 3) will execute the lines of code contained in the function with a = 1 and b = 3. The value that is returned "replaces" the function call. So now the line of code looks like var i = 4;. Although this is not exactly how it works, it's a good way to conceptualize it. This is a special case because you aren't actually running the inner method here, you're passing it as a variable.
Let me know if you have any more questions!
To understand why the inner function's return statements would not have an effect on the return statement in the outer scope, you need to understand how the Array.prototype.sort() function works.
The function arr.sort([compareFunction]), takes a function as a parameter.
compareFunction
Optional. Specifies a function that defines the sort order.
If omitted, the array is sorted according to each character's Unicode code point value,
according to the string conversion of each element.
The logic you write inside the compareFunction gets executed when
the java script engine tries to compare two elements during its
comparison operation.
Hence for each comparison that it makes, the function would return a
value, based on which the elements would be ordered.
This implies that the compareFunction that we pass on as a parameter
would be used to just obtain a value based on which two elements can
be compared and not exit the sort operation, leave alone exiting the
outer function.
Having said this, the code return objArr;, takes no effect, since the array would be sorted in place.

NewBee on NodeJs or PhantomJS: Function names on Javascript

I am just learning NodeJS and/or PhantonJS.
As a programmer with a lot of C experience, I do not like the way NodeJs code is written and find it a bit messy/unreadable. (Sorry if I ruffled any feathers)
In spirit of cleaning up the code, I was trying to do this and found a block.
In C or C++, we should be able to pass a function by name but in NodeJS/PhantomJS it does not seem to work.
Am I doing somthing wrong ?
Can someone explain to me how this is looked at by the Javascript interpreter ?
var page = require('webpage').create();
var printS = function (s) {
console.log(s);
phantom.exit();
}
/* This works */
page.open('http://net.tutsplus.com', function (s) {
console.log(s);
phantom.exit();
});
/* This does not work
page.open('http://net.tutsplus.com', printS(status));
*/
/*But this works
page.open('http://net.tutsplus.com', function (s) { printS(s);} );
*/
page.open('http://net.tutsplus.com', printS(status));
fails because you're not passing the function but rather the result of invoking the function on status. If you want to pass the function, you'd do it this way
page.open('http://net.tutsplus.com', printS);
I thought it might be helpful to have a more extensive explanation. Let's start simple:
In JavaScript, we have values and variables. Variables are containers for values. Almost everywhere where we can use values, we can use variables.
In JavaScript source code, we express values through literals, e.g. the number literal 42. We can directly pass that value to a function:
f(42);
Additionally, instead of passing the value directly, we can pass a variable to the function:
var v = 42;
f(v);
That is, we can substitute values with variables.
Lets consider
var printS = function() { ... };
This clearly is a variable whose value is a function. If we'd directly pass that value to a function (i.e. we pass a function to a function), it would look like:
f(function() { ... }); // similar to f(42)
That's exactly what you have in your first case:
page.open('http://net.tutsplus.com', function (s) {
// ...
});
Since we know that we can replace values with variables, we can just substitute function() { ... } with printS:
var printS = function() { ... }; // similar to var v = 42;
f(printS); // similar to f(v)
So your example would become
page.open('http://net.tutsplus.com', printS);
What is wrong with
page.open('http://net.tutsplus.com', printS(status));
then?
Notice that you added additional characters after printS, namely (status). They don't appear in the your first example where you inlined the function:
page.open('http://net.tutsplus.com', function (s) {
// ...
});
There is no (status) here. Hence these two constructs cannot be not equivalent.
page.open accepts a function value as second argument, but printS(status) doesn't evaluate to the function printS, it calls the function printS and passes the return value to page.open.
Why does
page.open('http://net.tutsplus.com', function (s) { printS(s);} );
work?
Lets remove the content and the argument of the function, and it becomes:
page.open('http://net.tutsplus.com', function () { ... } );
That looks exactly like one of the examples above. function () { ... }, is a function literal, so to speak. It creates a function value. There are no (...) after it which would call the function.
This doesn't work as you hope because page.open wants a function as its second argument... this callback pattern is very common in JavaScript. In your doesn't-work example, printS is being called with status as its argument, and it returns undefined. As undefined is not a function, it doesn't behave as you wish.
In your browser console or the node repl:
> printS = function (s) { console.log(s); };
function (s) { console.log(s); }
> typeof printS('hi');
hi
"undefined"
> typeof function (s) { printS(s); };
"function"
Another thing to know about JavaScript is that its dynamic typing and fairly generous type coercion can result in baffling behavior with no helpful errors to point you towards the root cause of your problem. A debugger or copious use of console.log() is frequently helpful in understanding these sort of problems.

Categories