What is the difference between naming functions or not in javascript? - javascript

What is the difference between
settings = {
edit: function (key, value) {
return anotherFunction(key, value) {
return value * 2;
};
}
};
and
settings = {
edit: function edit(key, value) {
return anotherFunction(key, value) {
return value * 2;
};
}
};
?

There's no difference when executing.
However, in the second case (named function), you can call the function recursively easier because it has a name.
For example, with a named function you can do:
fact: function factorial(n) {
if(n == 0) return 1;
return n * factorial(n-1); //You can do this with a named function easily
}
Without a name, this would be tricky.
Cheers

The essential difference is better debugging. In your developer tools, the named function in your second example will appear as edit in a backtrace; your first example will appear as anonymous. This can be extremely confusing when you're 10 function deep, and they are all called anonymous.

There are three reasons to give a function an inherent name. The first is that everyone does it. It's what everyone is used to.
function factorial(n) {
var accum = 1, i;
for (i = 1; i <= n; i++) {
accum *= i;
}
return accum;
}
The second is to understand stack traces better, as #meagar wrote.
The third is to let you write call functions recursively.
var factorial = function(n) {
var a = 1;
return (function factRecursive(k, a) {
if (k >= 2) {return factRecursive(k - 1, k * a)}
else {return a;}
})(n, a);
}

Related

Higher-order function

I have an exercise about JavaScript. This exercise requires me to use higher-order functions. I have managed to specify some of the functions so far, but when I try to execute the code, the result does not seem to work properly. I have some images to give you an idea, hopefully, you can help me correct this.
The thread is: Write the function loop(loops, number, func), which runs the given function the given number of times. Also write the simple functions halve() and square().
This is my code:
function loop(loops, number, func) {
var loops = function(n) {
for (var i = 0; i < n; i++) {
if (i < 0) {
console.log('Programme ended')
}
if (i > 0) {
return n;
}
}
}
}
var halve = function(n) {
return n / 2
}
var square = function(n) {
return n ** 2;
}
console.log(halve(50));
console.log(loop(5, 200, halve));
console.log(loop(3, 5, square));
console.log(loop(-1, 99, halve));
Your current loop function declares an inner function and then exits. Ie, nothing actually happens -
function loop(loops,number,func){
// declare loops function
var loops= function(n){
// ...
}
// exit `loop` function
}
One such fix might be to run the supplied func a number of times in a for loop, like #code_monk suggest. Another option would be to use recursion -
function loop (count, input, func) {
if (count <= 0)
return input
else
return loop(count - 1, func(input), func)
}
function times10 (num) {
return num * 10
}
console.log(loop(3, 5, times10))
// 5000
so first things first: Higher-Order functions are functions that work on other functions.
The reason why you get undefined is because you are calling a function which doesn't return anything.
function x(parameter){
result = parameter + 1;
}
// -> returns undefined every time
console.log(x(5));
// -> undefined
function y(parameter){
return parameter+1;
}
// -> returns a value that can be used later, for example in console.log
console.log(y(5));
// -> 6
Second, you are using n for your for loop when you should probably use loops so it does the intended code as many times as "loops" indicates instead of the number you insert (i.e. 200, 5, 99).
By having the "console.log" inside a loop you may get a lot of undesired "programme ended" in your output so in my version I kept it out of the loop.
The other two answers given are pretty complete I believe but if you want to keep the for loop here goes:
function loop(loops, number, func){
if(loops>0){
for(let i = 0; i< loops; i++){ // let and const are the new ES6 bindings (instead of var)
number = func(number)
}
return number
}
else{
return "Programme ended"
}
}
function halve(n) { // maybe it's just me but using function declarations feels cleaner
return n / 2;
}
function square(n) {
return n ** 2;
}
console.log(halve(50));
console.log(loop(5, 200, halve));
console.log(loop(3, 5, square));
console.log(loop(-1, 99, halve));
Here's one way
const loop = (loops, n, fn) => {
for (let i=0; i<loops; i++) {
console.log( fn(n) );
}
};
const halve = (n) => {
return n / 2;
};
const square = (n) => {
return n ** 2;
};
loop(2,3,halve);
loop(4,5,square);

Javascript Closure not taking inputs consistently

I have two javascript closures and I'm trying to understand why one will accept and input with a particular syntax and the other will reject.
function multiply(factor) {
var ace = (function(number) {
return number*factor;
});
return ace;
}
var yup = multiply(4);
console.log(yup(5));
This outputs 20 to the console as it should.
The second Closure I have is
var k = 3;
var add = (function () {
console.log(k);
var counter = k;
return function (j) {counter += 1; return counter*j}
})(k);
add();
console.log(add(5));
The output is 20 as it should be.
This issue I'm having that if I try to use the syntax of
(function() {
})(number);
In the first closure it does not work and outputs "number is not defined"
And if I try to input into the second closure
(function (k) {
var counter = k;
return function (j) {counter += 1; return counter*j}
});
I get out
function (j) {counter += 1; return counter*j}
to the console.
My question is, what am I not understanding about closers the () at the end of them.
The difference is whether you are creating the closure right away through an IIFE, or a function that makes the closure when called.
Your first snippet written in the second style would be
var yup = (function multiply(factor) {
return function ace(number) {
return number*factor;
};
})(4); // the multiply(4) call is inlined into the statement with the definition
console.log(yup(5));
Your second snippet written in the first style would be
function makeAdd(k) {
console.log(k);
var counter = k;
return function (j) {
counter += 1;
return counter*j;
}
}
var add = makeAdd(3);
add();
console.log(add(5));

add a memoization to recursive algorithm

I have written a function for partitioning a number:
var combinations = function (i) {
var mem = [];
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
return inner(i, [], 1);
}
In second step I would like to add a memoization to this algorithm, but can't think of implementing it the right way, beause there is no return statement until the very end (when return is specified e.g. in faactorial or fibbinacci I can add the memoization).
Can anybody drive me to the right direction?
[edit]
I need this algorithm to be as fast as possible. This is a competition for a kata at codewars: link
There is a requirement it must be executed under 6000ms for input up to 330.
That's the best algorithm I can think of, except how to store the partial results.
Here's a much simpler code that works:
function nr_partitions(n) { return p(n, n); }
function p(sum,largest) {
if (largest == 0) { return 0; }
if (sum == 0) { return 1; }
if (sum < 0) { return 0; }
return p(sum, largest-1) + p(sum-largest, largest);
}
It uses a well-known recurrence, p(n,k) = p(n,k-1) + p(n-k, k), where p(n.k) denotes the number of partitions of n where the largest part is at most k (e.g. p(3, 2)=2 because we only count 1+1+1,1+2, but not 3). For k=n we get the number of all partitions of n.
Adding memozation involves storing dictionary mapping pairs (sum, largest) to p(sum, largest).
I would go along the lines of:
var cache = {};
var combinations = function (i) {
if ( cache[i] ){
return cache[i];
};
var mem = [];
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
cache[i] = inner(i, [], 1);
return cache[i];
}
But you'll have to modify your algorithm to make use of that cache (compute the biggest terms first ?)
Depending on your other requirements, you might want to consider using underscore.js which has its own _.memoize function.
The secret of memoization is that it exploits how closures work. When you define a function inside another scope, it has access to everything in that scope. When you return that function to somewhere outside the scope, it carries references to everything it can see inside the scope.
So to implement memorization, you need to make a function that returns another function, one that does the memorization check before calling the inner one.
Your code will look something like this:
/**
* Because we'll be returning "a function that returns a function" below,
* this needs to be executed immediately so combinations() is just
* a standalone function.
*/
var combinations = (function(i) {
/**
* mem needs to stay outside the scope of your inner function.
* If it's in a closure like this, JavaScript will keep its value
* around as long as combinations still exists.
*/
var mem = [];
/**
* A memoization wrapper should return a memoized function
*/
return function(i) {
/**
* Check if mem[i] is set and return it if it has been
*/
if(mem[i] !== undefined) {
console.log('returning memoized value');
return mem[i];
}
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
/**
* If the value needs to be computed, we can set it at the same time
* as we return it instead of putting it in a temporary variable.
*/
console.log('computed');
return mem[i] = inner(i, [], 1);
}
}()); /** <--- That's the rest of the automatic execution */
console.log(combinations(5));
console.log(combinations(5));

Javascript - how to detect how many functions are being called? (multiple parentheses)

Let me propose an example that works, then follow up with what fails, highlighting the point to my question.
Here, we have 3 functions being called (1 named, 2 anonymous):
var add = function(a, b) {return a+b};
var multiply = function(a, b) {return a*b};
function myFunction(fxn) {
return function(x) {
return function(y) {
return fxn(x,y);
}
}
}
myFunction(add)(2)(3)
Understandably, this call fails:
myFunction(add)(2)(3)(4)
How would I detect how many functions are being called? In the 2nd call, I'm calling 4 functions (1 named, 3 anonymous).
How would I rewrite the myFunction function in a way that compensated for any given amount of calls? I know we can detect how many arguments a function was given, but is there a way to detect how many functions are being called? I hope I worded this correctly. Thanks.
To find out if a variable contains a reference to a function you can use below code:
if (typeof(v) === "function") alert("This is a function")
Based on above you can find out on how many nested functions there are
function myFunction() {
return function() {
return function() {
return 1 + 2;
}
}
}
var count = 0;
var v = myFunction();
while (typeof(v) === "function") {
count++;
v = v();
}
alert("Nr of nested functions: " + count)
Even if this has no practical use case I can think of, this is a possible solution:
var add = function(a, b) {
return a + b
};
var multiply = function(a, b) {
return a * b
};
var counter = 0;
var result = 0;
function myFunction(fxn) {
counter = 1;
result = 0;
return function first(x) {
++counter;
return function second(y) {
++counter;
x = result ? result : x;
result = fxn(x, y);
return second;
}
}
}
myFunction(add)(1)(2)(3)(4);
alert('Result is: ' + result + '; Parentheses count: ' + counter);

Insert a line into a function in JavaScript

In JavaScript, is it possible to insert a line into a function that already exists? I want to create a function that inserts a line at a specific position in a function:
function insertLine(theFunction, lineToInsert, positionToInsert){
//insert a line into the function after the specified line number
}
For example, would it be possible to programmatically insert the line checkParameterTypes(min, "string", max, "string"); before the first line of this function?
function getRandomInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
If you want something to happen at the beginning of a function, you can use the following. You do have access to this and the arguments from your injected function. So it will still work for functions that require a specific context.
function inject(before, fn) {
return function(){
before.apply(this, arguments);
return fn.apply (this, arguments);
}
}
For example
function add(a, b) {
return a + b;
}
function concat(a, b) {
return a + b;
}
/**
* You can repeat index and type to check multiple arguments
*/
function createArgumentChecker(index, type /**index, type, ... */) {
var originalArgs = arguments;
return function() {
for (var i=0; i < originalArgs.length; i+=2) {
var index = originalArgs[i],
requestedType = originalArgs[i+1],
actualType = typeof arguments[index];
if (typeAtIndex != actualType) {
console.log("Invalid argument passed at index " + index +
". Expected type " + requestedType + "but it's " + actualType );
}
}
}
}
function logArguments() {
console.log(this, arguments);
}
// Inject an argument checker
add = inject(add, createArgumentChecker(0,"number", 1, "number"));
concat = inject (concat, createArgumentChecker(0, "string", 1, "string"));
// You can even do it multiple times, inject an argument logger;
add = inject(add, logArguments);
concat = inject(concat, logArguments);
JSfiddle
This can be handy when debugging websites that you can't modify the source code, I wouldn't use it do parameter checking unless you can strip it our for the production version.
Yes you can but using eval is always evil ;)
function insertInbetween (arr, value, index) {
var inserted, i, newarr = [];
for (i = 0; i < arr.length; i++) {
if(i == index && !inserted) {
newarr[i] = value;
inserted = true;
}
newarr.push(arr[i]);
}
return newarr;
}
function test (a, b) {
console.log(a,b);
}
var fstrarr = test.toString().split('\n');
eval(insertInbetween(fstrarr, "console.log('injected!');", 1).join('\n'));
Edit:
As mentioned in the comments to your question you'll loose scope by doing so.

Categories