Functions in javascript and scopes - javascript

Here i have simplified my problem to this code. I need to build a table. I have 3 functions(one,two,three) that have specific functionality, and i have a main function that builds a table from the return of this 3 functions. However i don't fully understand how to finish this.
function foo(one,two,three){
var result = "";
for (var i=0;i<arguments.length;i++){
result+= arguments[i](true);
result+= arguments[i](false);
}
console.log(result);
}
foo(one);
There could be 2 more functions, but in this case it doesn't matter i wrote only one. So the one() can accept 2 arguments(true or false) and
function one(arg){
if(arg == true){
this.result += "1-true";
} else if(arg ==false){
this.result += "1-false";
}
return this.result;
}

When you call a function, it won't inherit the scope from the calling code, so the property this.result in the one function won't be the same as the local variable result in the foo function.
Unless you call a function as a method of an object, the context of the function (this) will be the global window object. Inside the one function this.result will be the same as window.result. As the window object is the global context, you will create a global variable named result.
The variable result declared inside the foo function is local to that function, and it's separate from the global result variable. From the one function you can't even reach the result variable in foo function at all.
As the one function is using a global variable that is never assigned a value, it will contain undefined from the start. Adding "1-true" to it will convert undefined into the string "undefined" and the result is "undefined1-true". In the next call to one the value in the global variable is still there, so it will add "1-false" to it, making it "undefined1-true1false". As the foo function adds the values from the first and the second call to one, the result is "undefined1-trueundefined1-true1-false".
If you would use the global variable in both functions so that they used the same variable (which is what it seems that you tried to do), you would get a different result. The one function would add "1-true" to the variable and then return the variable. The foo function would then add the returned value to the variable, making it "1-true1-true". The next call to one would add "1-false" to the variable making it "1-true1-true1-false" and then return the value of the variable, which the foo function adds to the variable, making it "1-true1-true1-false1-true1-true1-false".
Instead of adding to the variable in both functions, you should just return a string from the one function, and put the strings together in the foo function:
function foo(one,two,three) {
var result = "";
for (var i = 0; i < arguments.length; i++) {
result += arguments[i](true);
result += arguments[i](false);
}
console.log(result);
}
foo(one);
function one(arg) {
if(arg == true) {
return "1-true";
} else if (arg == false) {
return "1-false";
}
}
Note: Instead of using if (arg == true) you can just use if (arg), and the else if() can just be an else:
function one(arg) {
if(arg) {
return "1-true";
} else {
return "1-false";
}
}
You can also use the conditional operator to get the same result:
function one(arg) {
return arg ? "1-true" : "1-false";
}
If you still want to use a variable in the one function, you don't need to use the += operator as you only have one string. You can just assign the value:
function one(arg) {
var result;
if(arg) {
result = "1-true";
} else {
result = "1-false";
}
return result;
}

Try to change condition for function one:
var result = '';
if (arg) { .... } else { ... };
return ...;

Thanks for suggestions, considering all the answers above i figured out the solution.
function foo(one, two,three) {
//Vehicle parts
var vhcparts = {
a: "cabin",
b: "wheel",
c: "body",
d: "trail",
e: "back",
f: "doublewheel",
g: "triplewheel",
h: "fourwheel",
i: "aftercabin",
j: "bodybegin"
}
//Final image string + 2chars, to add extra space at front and back;
var imageDescription = "aijbcccccccge" // obj.imageDescription;
imageDescription = "-" + imageDescription + "-";
//Iterate throught list of arguments to build specific line of TruckMainBoard
var result = "";
for (var i = 0; i < arguments.length; i++) {
result += "<tr>";
//Iterate throught image string to generate td and populate it
for (var j=0;j<imageDescription.length;j++){
// Verify if imageDescription string matches vhcparts(vehicle parts) array.
for (var p in vhcparts){
// var counter = 0;
if(imageDescription[j] == p
&&
(imageDescription[j] == "a" ||
imageDescription[j] == "b" ||
imageDescription[j] == "f" ||
imageDescription[j] == "g" ||
imageDescription[j] == "h"
)
)
{
result += arguments[i](true);
}
else if(imageDescription[j] == p) {
result += arguments[i](false);
}
}
}
result += "</tr>"
}
console.log(result);}
function one(arg){
var result = "";
if(arg){
result += '<td><img src="images/';
//result += vhcparts[p];
result +='.png">';
result +='</td>';
} else {
console.log("nothing to print")
}
return result;
}
foo(one,two);

Related

How to reuse a closure function assigning it to a variable or constant in JavaScript

I'm solving an exercise that is intended to use closures. You must create a function that returns a function that will store a value and, when you reuse it, add the new value to the saved one.
const firstValue = myFunction(3);
const secondValue = firstValue(4);
// result => 7
this is the code that I'm using to practice closures:
function addNumbers(num) {
let storage = 0
let n = num
function adding(n) {
storage += n;
return storage
}
return adding(n)
}
let firstAttemp = addNumbers(4)
let secondAttemp = firstAttemp(3)
console.log(firstAttemp)
this throw an error "Uncaught TypeError: firstAttemp is not a function"
const addNumbers = (a) => (b) => a + b
It's called currying, more details here.
P.S.
If you want to use function syntax, it will look like this:
function addNumbers(a) {
return function (b) {
return a + b
}
}
As #skara stated in their comment, return adding(n) returns the result of calling adding instead of returning the function so that it may be called later with firstAttemp(3).
Unfortunately though it still doesn't work because you don't actually assign the value passed to addNumber to be added later.
function addNumbers(num) {
let storage = 0;
let n = num;
function adding(n) {
storage += n;
return storage;
}
return adding;
}
let firstAttemp = addNumbers(4);
let secondAttemp = firstAttemp(3);
console.log(firstAttemp);
console.log(secondAttemp); // 3! 😢
You don't actually need to manually save the value of num to a variable as it is captured in the closure arround adding that is being returned.
function addNumbers(num) {
function adding(n) {
return num + n;
return storage;
}
return adding;
}
let firstAttemp = addNumbers(4);
let secondAttemp = firstAttemp(3);
console.log(secondAttemp); // 7 👍🏻

I keep getting "undefined" as an error, function not returning anything

I've been trying to figure out why I keep getting undefined, and I don't really see why, I know that I would get undefined if my function isn't returning anything, but in this case, even with returning in two places, I am still getting undefined. I think that the reason for that is that maybe I am not returning the value from innerFunc properly? I'm thinking maybe there's something wrong with my syntax here: innerFunc(arg) but I'm not sure how it is wrong, or what to change it to.
Any help would be appreciated.
Instructions:
Create a function "fastCache" that takes one argument (a function) and returns a function. When fastCache is invoked it creates an object that tracks calls to the returned function, where each input to the returned function is associated with its output. Every subsequent call to that returned function with the same argument will return the output directly from the object, instead of invoking the original function again.
function fastCache(func) {
const obj = {};
function innerFunc(arg) {
for (const key in obj) {
if (key === arg) {
return obj[arg]
} else {
obj[arg] = innerFunc(arg)
return innerFunc(arg)
console.log(obj[arg])
console.log(arg)
console.log(innerFunc(arg))
}
}
}
return innerFunc
// console.log(innerFunc(arg))
}
//example:
//SINGLE ARGUMENT CASE
const multiplyBy2 = num => num * 2;
const cachedMultiplyBy2 = fastCache(multiplyBy2);
If you want a simple cache function:
function cacheWrapper(fn) {
let cache = { };
return arg => {
if (cache.hasOwnProperty(arg)) {
return cache[arg];
}
return cache[arg] = fn(arg);
};
}
function test(x) {
return x * 2;
}
let testCached = cacheWrapper(test);
console.log(testCached(2));
console.log(testCached(2));
The key here is hasOwnProperty which will tell you if that cache slot is occupied or not. This avoids having to fumble around and find out the hard way with iteration.
If the number isn't already in the object, it won't be found in the loop.
function fastCache(func) {
const obj = {};
function innerFunc(arg) {
for (const key in obj) {
if (key === arg) {
return obj[arg]
}
}
obj[arg] = func(arg)
return func(arg)
}
return innerFunc
// console.log(innerFunc(arg))
}
//example:
//SINGLE ARGUMENT CASE
const multiplyBy2 = num => num * 2;
const cachedMultiplyBy2 = fastCache(multiplyBy2);
const result = cachedMultiplyBy2(8);

Add callback to for loop function

I have a function to which I pass an array or an object, then it looks for specific keys and edits their values accordingly,
function iterate(obj, delta) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property],delta);
} else {
if(property === 'unix_time'){
var bee = parseInt(obj[property]);
var b = bee + parseInt(delta);
obj[property] = b;
}
}
}
}
}
Basically, it looks for the "unix_time" key and add a number "delta" to it.
Question: When I call it asynchronous, it becomes undefined, How can I add a callback that I can simply use to determine that the function has finished executing. Or maybe should I add a promise to it?
For example when i run this it returns perfectly
console.log("new one", obj);
iterate(obj, 3600000)
But this is a problem, it becomes undefined
var dd = iterate(obj, 3600000);
res.status(200).send(JSON.stringify(dd));
As mentioned in comments, you function is synchronous and it returns immediately after you call it like this:
var result = iterate(tree, delta);
However, as it's currently written, the result variable will have value of undefined since your iterate function doesn't return anything.
If you have the setup like this:
var obj = {...};
iterate(obj, 3600000)
console.log(obj) // correctly outputs modified object
It will output modified object, since you're not using here the returned value from the function. However, in this scenario:
console.log("new one", iterate(obj, 3600000)); // ouputs `undefined`
the returned value is used and it's undefined.
Using the use case you provided, you can modify the usage like this:
iterate(obj, 3600000);
res.status(200).send(JSON.stringify(obj));
and it will work fine. Or you need to modify iterate to return value. Provide an example of obj so I can write a modification to your iterate function.
Modified the iterate function:
function iterate(obj, delta) {
obj.forEach(function (element) {
if (element.hasOwnProperty('unix_time')) {
element['unix_time'] = parseInt(element['unix_time']) + parseInt(delta);
}
});
return obj;
}
I don't know I understand your question. But, if you want to use a callback, you should split this funcion in two. One for main operation and another for recursivity.
i.e.
function iterate(obj, delta, callback) {
interate_recursive(obj, delta);
if(typeof callback != 'undefined')
return callback();
else return obj;
}
function interate_recursive(obj,delta){
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property],delta);
} else {
if(property === 'unix_time'){
var bee = parseInt(obj[property]);
var b = bee + parseInt(delta);
obj[property] = b;
}
}
}
}
}

Passing a function as argument which uses the argument of parent function but also has it's own argument

I just started playing around with functional programming and am trying to pass a function as an argument of another function. However the function that I am trying to pass also has arguments like so:
function splitStringBy(string, type, func) {
// Split string by type.
var splitArray = string.split(type);
console.log(splitArray);
// Do something with the array.
func !== undefined ? func(splitArray) : null;
}
function loopArray(array, func) {
// Loop through array.
for (var i = 0; i < array.length; i++) {
func(array[i]);
}
}
I need to pass splitArray to my loopArray()
Here's how I'm trying to call it:
splitStringBy($scope.textSpace, "<br>", loopArray(splitArray, function() {
console.log('It worked!');
}));
Console comes up with Error: splitArray is not defined.
Rather than passing loopArray as a function, you're actually calling it, then passing its return value to splitStringBy. Since splitArray isn't defined when you first reference it, it's throwing that error.
What you want to do is something like this:
function splitStringBy(string, type, func) {
// Split string by type.
var splitArray = string.split(type);
console.log(splitArray);
// Do something with the array.
func !== undefined ? func(splitArray) : null;
}
function loopArray(func) {
// Return function for looping.
return function(array) {
// Loop through array.
for (var i = 0; i < array.length; i++) {
func(array[i]);
}
}
}
splitStringBy($scope.textSpace, "<br>", loopArray(function() {
console.log('It worked!');
}));
This is called currying, where a function passes a function as a return value. loopArray will create a function, then return it. We then pass the newly made function to splitStringBy, which then invokes it.

Javascript function call with another function as parameter

I have a few functions in two different files that are all linked together by function calls they are as follows
FILE 1:
function getFunction(func){
}
FILE 2:
function Numbers(one, two) {
return (one*two);
}
var func = getFunction(Numbers);
and these are called by:
func(input_array);
my array has values 1,3,5,7,9 and I need func(input_array) to return 3,15,35,63,9 (the last value loops back to the first value)
basically what I am trying to do is have getFunction return a function such that these values are calculated. I am having trouble because I can't wrap my mind about sending and returning functions. I don't know how to access the array if it isn't sent into the function. Let me know if I need to clarify anything.
function getFunction(callback) {
return function(array) {
return array.map(function(cur, index) {
return callback(cur, array[(index+1) % array.length]);
});
};
}
getFunction returns a closure over the callback parameter, which is the function that you want to call. The closure receives the array parameter, and it calls the callback in a loop over the array using array.map. The % modulus operator performs the wraparound that you want.
Another way to write this that may be clearer is:
function getFunction(callback) {
return function(array) {
var result = [];
for (var i = 0; i < array.length; i++) {
j = (i+1) % array.length; // Next index, wrapping around
result.push(callback(array[i], array[j]));
}
return result;
};
}
var func = getFunction(Numbers);
console.log(func([1,3,5,7,9])); // Logs [3,15,35,63,9]
here is simple function that returns what you need
function Numbers(x) {
output_array=[];
for(i=0;i<x.length;i++){
if(x[i+1]==undefined){
output_array.push(x[i]);
}
else{
output_array.push(x[i]*x[i+1]);
}
}
return output_array;
}
var input_array=[1,3,5,7];
var num = Numbers(input_array);
console.log(num);
OR if you need it in the way function calling another function
and than returning the result use this
function getFunction(Numbers,input_array){
return Numbers(input_array);
}
function Numbers(x) {
output_array=[];
for(i=0;i<x.length;i++){
if(x[i+1]==undefined){
output_array.push(x[i]);
}
else{
output_array.push(x[i]*x[i+1]);
}
}
return output_array;
}
var input_array=[1,3,5,7];
var num = getFunction(Numbers,input_array);
console.log(num);

Categories