Alternative syntax for closures in Javascript: possible drawbacks? - javascript

I am still fighting my battle against my low IQ :D
This is the usual infamous cycle with closures:
function r(){
var a = [];
var i;
for(i=0;i<10;i++){
a[i]=(function(x){
return function(){return x;}
})(i);
return a;
}
This is quite clear to me now.
In order to understand closures better, I played with the code and came up with:
function r(){
var a = [];
var i;
for(i=0;i<10;i++){
a[i] = (function(){
var x=i;
return function(){return x;}
})();
}
return a;
}
Is my code fully equivalent?
Merc.

Is my code fully equivalent?
Yes.
I find it slightly easier to read the second way, because it saves having to look to the end of the immediately-executed function to find out what's passed in as a parameter (not that that's a big problem with short functions like this), but the first way is more compact and probably more common so...

I guess you didn't try them, the first one doesn't even work! Use firebug to test your code. Here is a version of the first example which actually doesn't give errors:
function r() {
var a = [];
var i;
for (i=0; i<10; i++) {
a[i] = (function (x) {
return function () {
return x;
}
})(i);
}
return a;
}
So, after adding the missing closing brace, they are equivalent, they build an array of functions that return the numbers from 0 to 9, they don't build an array of numbers from 0 to 9. So for example, calling r()[5](); returns 5 (is the sixth element of the array).

Related

JS: Higher Order Function Problem; Accept Array and Callback Function --> don't understand

I have the following problem below:
My For Each
Write a function myForEach that accepts an array and a callback function. The behavior of myForEach should mirror the functionality of the native .forEach() array method as closely as possible.
Below is the code:
let sum = 0;
function addToSum(num) {
sum += num;
}
let nums = [10, 20, 30];
function myForEach(anArray, callback){
for (let i=0; i<anArray.length; i++){
let num = anArray[i];
//console.log(num)
// I don't understand what this line of code is doing...
callback(num, i, anArray);
}
return undefined
}
myForEach(nums, addToSum);
console.log(sum); // 6
The above code works in this higher order function problem but I don't understand why. Specifically, what is the following line of code mean:
callback(num, i, anArray);
why are there 3 arguments? and where are these arguments getting passed to?
"as closely as possible" is quite a harsh requirement. Javascript built-in functions are very complicated! These are the steps that the standard requires you to implement:
http://www.ecma-international.org/ecma-262/7.0/#sec-array.prototype.foreach
In layman's terms, since JS is a highly dynamic language, when you design a built-in function, you cannot just rely on parameters being what you expect them to be. In case of forEach:
the argument can be not an array, and even not an object
it might not have length or its length might be not a number
the callback might be missing or be not a function
and so on. That's why an "as close as possible" implementation should do lots of safety checks before it actually starts looping and calling.
You can find an example of a real-world forEach polyfill on the MDN page (only look if you decided to give up on this):
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Read here about it. Javascript doesn't care how many parameters you pass. For example, the following code still works but alerts undefined in the addToSum function:
let sum = 0;
function addToSum(num, i, k, j) {
sum += num;
console.log("i is:" + i);
console.log("k is:" + k);
console.log("j is:" + j);
}
let nums = [10, 20, 30];
function myForEach(anArray, callback) {
for (let i = 0; i < anArray.length; i++) {
let num = anArray[i];
//console.log(num)
// I don't understand what this line of code is doing...
callback(num);
}
return undefined
}
myForEach(nums, addToSum);
console.log(sum);
So the thing that happens in your original code is that i and anArray that you pass does not effect the addToSum function at all, and the only parameter this function need is num so everything works good.
It's a callback function:
callback();
This is the function you passed into myForEach - in your code, it's addToSum, but it's a reference with a different name. It's used in case you have different functions for handling different things. In your code you can just as easily use addToSum and forget about callback altogether:
let sum = 0;
function addToSum(num) {
sum += num;
}
let nums = [10, 20, 30];
function myForEach(anArray) {
for (let i = 0; i < anArray.length; i++) {
let num = anArray[i];
//console.log(num)
// I don't understand what this line of code is doing...
addToSum(num, i, anArray);
}
return undefined
}
myForEach(nums, addToSum);
console.log(sum);

Memoization javascript

I'm studying JavaScript from the book JavaScript: The Good Parts, in the memoization section there is an example about using memoize technique to do Fibonacci problem
We create a general function call memoizer, it takes an memo array and the fundamental function, returns a shell function that manages the memo and calls fundamental function
var memoizer = function(memo, fundamental) {
var shell = function(n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fundamental(shell, n);
memo[n] = result;
}
return result;
};
return shell;
};
And then create fibonacci like this:
var fibonacci = memoizer([0, 1], function(shell, n) {
return shell(n-1) + shell(n-2);
});
If I run fibonacci(10), the result will be displayed exactly.
But the thing that makes me confused is the n parameter shell function in memoizer function. I know that it is the value that we want to compute. But where is it come from? How can I call fibonacci(10), for example, can pass the value 10 to n? And what is exactly the var fibonacci? Is it a function or points to a function object as memoizer?
Thanks for any help!
So, to understand this fully, you need to understand things below as fundamental pieces.
Closure How do JavaScript closures work?
Scope What is the scope of variables in JavaScript?
First class object What is meant by 'first class object'?
So, now look at the code.
var memoizer is assigned as a function that returns an another function inside.
var memoizer = function(memo, fundamental) {
var shell = function(n) {
... do some works ...
};
return shell;
};
Can you see it? var shell is returned at the end of the line in memoizer
And whatever the inner logic is in memoizer, the result of it is assigned to var fibonacci
var fibonacci = memoizer([0, 1], function(shell, n) {
return shell(n-1) + shell(n-2);
});
So, it means fibonacci equals the result of memoizer (Since we excuted it), and the result of memoizer equals shell function. If you read those links given to you by me well, you can understand what is going on behind the scenes.
By the way, the code you've given isn't the best way. Because anyway closure makes an activated object alive that isn't necessary.
This code below is an another way of making fibonacci, this isn't the absolute best way, however, I recommend you to compare this code with your code, and figure the differences out.
var result = [];
result[0] = 1;
result[1] = 1;
function fibonacci(n){
var i;
for(i = 2; i < n; i++){
if(!result[i]){
result[i] = result[i-1] + result[i-2];
}
}
return result[i-1];
}
console.log(fibonacci(10));

Reasonable uses for closure?

Lately, I have been seeing in my companies production code return with closure functions. Such as return (function() {...}()); And I do not like to see this, but I am not an authoritative source. I thought I would ask StackOverflow why and when this good/bad to use.
* NOTE *
Say your not concerned about namespace pollution because all of these functions are already in their on closure.
Example1a:
function foo(bar) {
return {
x: 1 + bar,
y: 1 - bar,
duration: (function() {
var i = 0,
len = 5;
var results = 0;
for (; i < bar; i++) {
results += 1 + (results * bar);
}
return results;
}())
};
}
Example1b:
function barProcess(bar) {
var i = 0;
var len = 5;
var results = 0;
for (; i < bar; i++) {
results += 1 + (results * bar);
}
return results;
}
function foo(bar) {
return {
x: 1 + bar,
y: 1 - bar,
duration: barProcess(bar)
};
}
Example1c:
function foo(bar) {
var i = 0;
var len = 5;
var results = 0;
for (; i < bar; i++) {
results += 1 + (results * bar);
}
return {
x: 1 + bar,
y: 1 - bar,
duration: results
};
}
Observation:
Example1a:
The inner function takes advantage of closure if there is a need.
Example1b:
In case barProcess could require some closure which could make the argument list long and problematic to maintain.
Example1c:
There is no extra function creation per invocation.
It is easiest to debug (in my opinion).
Please if someone can give me some technical reasons for why Example a, b, or c should be used that would be fantastic.
So, my lame answer did not satisfy me, so I tried this. JS Perf Tests. Which I think to make my observations not too far off.
I don't think its possible to choose a clear winner between examples a,b anc c for every simple case.
In the example you give, version (c) is good enough so I would go with it. That said, version (a) keeps the i, len and results veriables in an even tighter scope so it definitely could be a good way to go if you want to keep "x" and "y" more separate from duration "b".
I'm not a fan of splitting things into separate named functions just for organizational or scoping reasons, like you did on example (b), because it tends to make the code more complicated and harder to follow. However, if the barProccess is an actual reuseable abstraction that you can give a clear name for then keeping it separate might be a good idea.
Say your not concerned about namespace pollution because all of these functions are already in their on closure.
I think you are exagerating a bit here. The inner IFFE is not 100% recommended like the outer IFFE is but restricting scope even more is still perfectly OK and I don't think its worth fighting against your coleagues over it.
1a: No closure is formed as the outer function, foo(), has not returned when the inner function executes. The inner function is an anonymous "self-executing" subroutine. Whereas a self-executing function can form a closure, this one neither does nor needs to. This is a slightly "showy" way to structure the code.
1b: No closure is formed as the outer function, foo(), straightforwardly calls the named function barProcess(), which returns a numeric value, not a function. This approach would be useful if barProcess() is also to be called from elsewhere in the code.
1c: No closure is formed. foo() comprises a straightforward block of code, which is simple to understand and will certaily do the job. As javascript for loops don't have their own scope, foo() will simplify to :
function foo(bar) {
for(var i=0, results=0; i<bar; i++) {
results += 1 + (results * bar);
}
return {
x: 1 + bar,
y: 1 - bar,
duration: results
};
}

Recursion with names

I'm a little lost in general, but if someone could please briefly explain why this code works that would be great!
// Our array of messy words
var capitals = ["berlin", "parIs", "MaDRiD"];
// Capitalize function
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
// Our recursive function
function fixLetterCase(array, i) {
// Base case
if (i === array.length) {
return;
}
// Action
array[i] = capitalize(array[i]);
// Recursive case
return fixLetterCase(array, i + 1);
}
// Here is our function call
fixLetterCase(capitals, 0);
console.log(capitals);
While I understand this is not an answer to the question, I thought it might help to see a non-recursive version of the logic:
// Our array of messy words
var capitals = ["berlin", "parIs", "MaDRiD"];
// Simple function to capitalize word
function fixLetterCase(array) {
for(var i = 0; i < array.length; i++) {
array[i] = array[i].charAt(0).toUpperCase() + array[i].slice(1).toLowerCase();
}
}
fixLetterCase(capitals);
console.log(capitals);​
Here's a working fiddle to play with.
function fixLetterCase(array, i) {
// At some point, this is true, so the algorithm stops
if (i === array.length) { return; }
// At this point, the function did not returned. The function logic continues.
// Replace the array key with a new value = the return value of captialize()
array[i] = capitalize(array[i]);
// i increments by one, and the function itself is called again.
return fixLetterCase(array, i + 1);
}
// Initialize the function, with starting offset ("counter") i=0
fixLetterCase(capitals, 0);
// Our recursive function
function fixLetterCase(array) {
for (var i = 0, length = array.length; i < length; i++) {
array[i] = capitalize(array[i]);
}
}
Would probably be a better, more readable, more performant solution. This case does not need recursion at all, a loop should be more effective. You don't need that many function calls and you don't need to evaluate the array's length with every function call.
I assume you're talking about the recursive part. It's really just an exotic way to iterate over the array.
Conventionally you might do this with a for loop, following the pattern (forgive the totally weird pseudo-code, my own gross invention):
for ([initialization]; [condition]; [modification])
[function]
With recursion you can do it as:
[function [initialization]]
if [!condition]
break
[function [modification]]
I personally feel there's not much benefit to the recursive version in this case, as it's much less idiomatic and thus less obvious how it works; and it offers no performance benefit.
The function fixLetterCase is called with i equal to zero. When fixLetterCase runs for the first time, it calls capitalize on the first word in the array. In the recursive call, it increments i with 1 so that means it will capitalize the next word in the array. It will keep doing this until it reaches the end of the array.
That's why the function works: the index of the word that needs to be capitalized is incremented each time and in the last call, when the index is equal to the length of the array, the 'recursion' ends.
Note that this is not a typical use of recursion because there's nothing returned from the recursive calls. Also note that this could be written much more straightforwardly as a for loop.
This really doesn't need to be written recursivly, you could do the same thing with
// Our array of messy words
var capitals = ["berlin", "parIs", "MaDRiD"];
// Capitalize function
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
// Our recursive function
function fixLetterCase(array, i) {
// Action
array[i] = capitalize(array[i]);
}
// Here is our function call
for(var i = 0; i < capitals.length; i++)
{
fixLetterCase(capitals, i);
}
console.log(capitals);
The recursive part is only iterating through the capital words and escapes when you reach the end of the array. Hopefully reading it like this will make it more clear.

JavaScript differences defining a function

I just bought the newest version of "JavaScript: The Definitive Guide" and already have a question. :D
Are the following lines semantically the same:
var square = function(n){
return n * n;
};
and
function square(n){
return n * n;
}
If yes, what are the advantages/disadvantages of using either of them?
Thanks for your help!
Check this out:
a(); // prints 'A'
function a(){
console.log('A');
};
and this:
b(); // throws error. b is not a function
var b = function() {
console.log('B');
};
Did you notice the difference?
Yes, they do the exact same thing.
The main advantage of the first approach is that it gives you a reference to that function so that you could pass it to another function or attach it to an object if you need to.
Difference is that in the first solution, you can do that :
var square = function(n){
return n * n;
};
// some code
square = function(n) { return n*n*n; }
you have reference to a function. On the other solution, the function is statically declared.
Disclaimer: need JS guru to tell me if I'm wrong =).

Categories