Javascript return not working - javascript

I have this code:
function get_id_from_coords (x, y)
{
x = parseInt(x);
y = parseInt(y);
if (x < 0)
{
x = (x + 6) * 60;
}
else
{
x = (x + 5) * 60;
}
if (y < 0)
{
y = (y + 6) * 60;
}
else
{
y = (y + 5) * 60;
}
$('#planets').children().each(function(){
if ($(this).attr('x') == x) {
if ($(this).attr('y') == y) {
alert (parseInt($(this).attr('id')));
return parseInt($(this).attr('id'));
}
}
});
}
alert(get_id_from_coords(x, y));
However, from this code I get two popups:
First, from inside the function, I get the proper value (like 63), but then, when I alert the return value, I just get undefined.

You get undefined as you function doesn't return - the last statement is a call to each function and it's not a return statement. If you put a return, e.g.
...
return $('#planets').children().each(function(){
if ($(this).attr('x') == x) {
if ($(this).attr('y') == y) {
alert (parseInt($(this).attr('id')));
return parseInt($(this).attr('id'));
}
}
});
it will return something - in this case, based on the docs:
http://api.jquery.com/jQuery.each/
The method returns its first argument, the object that was iterated.
it will return the children of #planets.
If you want to find some value specifically using each, then you can do something like this:
...
val toRet;
$('#planets').children().each(function(){
if ($(this).attr('x') == x) {
if ($(this).attr('y') == y) {
toRet = parseInt($(this).attr('id'));
}
}
});
return toRet;

Related

Simplified javascript some function with almost the same code

Hei, I'm working an app to simulate prices. I have a code like this.
function max110(x) {
if (x >= '1' && x <= '50') {
var sum = 120 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '51' && x <= '100') {
var sum = 115 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '101' && x <= '200') {
var sum = 110 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else {
hasil.value = 'error!';
}
}
function max115(x) {
if (x >= '1' && x <= '50') {
var sum = 125 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '51' && x <= '100') {
var sum = 120 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else if (x >= '101' && x <= '200') {
var sum = 115 * x;
hasil.value = 'Rp.' + parseFloat(sum * 1000);
} else {
hasil.value = 'error!';
}
}
And I still have some functions similar to that, it almost the same code I'm trying to make it simple, is it possible to make it in 1 function only?
Try:
function maxval(x,maxval) {
if(x >= '1' && x <= '50'){
var sum = (maxval+10)* x;
hasil.value = 'Rp.'+parseFloat(sum*1000);
}
else if (x >= '51' && x <= '100'){
var sum = (maxval+5)* x;
hasil.value = 'Rp.'+parseFloat(sum*1000);
}
else if(x >= '101' && x <= '200'){
var sum = (maxval)* x;
hasil.value = 'Rp.'+parseFloat(sum*1000);
}
else{
hasil.value = 'error!';
}
}
By the way i assumed that maxval increments by 5, Cant get you a better solution without getting more details about functionality.
This would be my implementation. I don't agree with how you're handling your integers, but it's your coding style. I pass in an object of choice that has all of the values that I want. You don't need the logic, just the values. I hope nobody gets mad that I monkeypatch String. I'm assuming that your variable x is a string.
String.prototype.isBetween = function(lower, upper){
int = parseInt(this)
return int >= parseInt(lower) && int <= parseInt(upper)
}
max110 = {0: 120, 1: 115, 2: 110}
max115 = {0: 125, 1: 120, 2: 115}
function max(x, values) {
let sum
hasil.value = ''
if (x.isBetween('1', '50')) {
sum = values['0'] * x
} else if (x.isBetween('51', '100')) {
sum = values['1'] * x
} else if (x.isBetween('101', '200')) {
sum = values['2'] * x
} else {
hasil.value = 'error'
}
hasil.value = hasil.value ? 'error' : 'Rp.'+parseFloat(sum*1000);
}
function max(x, extra) {
var sum_number = extra;
if(x >= '1' && x <= '50'){
sum_number += 120;
}
else if (x >= '51' && x <= '100'){
sum_number += 115;
}
else if(x >= '101' && x <= '200'){
sum_number += 110;
}
if(x < 1 && x > 200){
hasil.value = 'error!';
} else {
hasil.value = 'Rp.'+parseFloat((sum_number) * x *1000);
}
}
parameter extra can be 0 or 5 for function max110 or max115
Basically, you have two function which works the same way and returns the same with different values.
The different values yould be stored in an array and you could use a single function for getting the index and then take the needed value out of the array with that index.
So you need a better organisation of types of the variables, which if uses as number, it should be number and also for comparison, then it should be a number on both sides of the condition.
Use a pure function, which does not alter a state of something, which is not given into the function.
Use a check in the function for unwanted values and exit early with a first check at the lower border, in your case, it is zero and below, return -1, because that is not an index of an array (and it is usually used to denote, that no index is found, like with Array#indexOf).
Then take the upper border for a check end exit early with a index value, no need for continuing else if structures.
At the end return as well -1 for not found index.
Together:
function getValue(x, maxArray) {
var index = getIndex(x);
if (index in maxArray) {
return 'Rp.' + maxArray[index] * x * 1000;
}
return 'error!';
}
function getIndex(x) {
if (!x || x < 0) {
return -1;
}
if (x <= 50) {
return 0;
}
if (x <= 100) {
return 1;
}
if (x <= 200) {
return 2;
}
return -1;
}
var max110 = [120, 115, 110],
max115 = [125, 120, 115];
console.log(getValue(-1, max110));
console.log(getValue(10, max110));
console.log(getValue(10, max115));

how to get the same result by using function and closure together in javascript

I need to make the following(below) function call to give the same result in both situations:
sum(5,4); // 9
sum(5)(4); // this should also print 9
I tried the following but it's not working:
function sum(x,y){
var a = x;
var b = y;
if (y == undefined && y == ''){
return function (a,b){
return a +b;
}
}
else {
return a +b;
}
}
Any suggestions?
Try to curry your function for your requirement,
function sum(x,y){
if(y === undefined){
return function(y){ return x+y; }
} else {
return x + y;
}
}
sum(5,4); // 9
sum(5)(4); // 9
The "cool" one line answer:
function sum(x, y){
return y != undefined? x+y : function(a){return x + a};
}
You should use logical OR(||), not AND(&&)
function sum(x,y){
if (y == undefined || y == ''){
return function (y){
return x + y;
}
}
else {
return x + y;
}
}
Careful: You probably won't need that functionality, it's simply redundant.
You can use conditioning like that:
function sum( x , y ){
if(y == undefined){
return function( y ){
return x + y;
};
}
else{
return x + y;
}
}

Determining factorial of a number

I'm new to javascript and I'm having a hard time figuring out how to get this factorial function to work. Here's my code now.
var x = prompt("Enter a number"); {
function fact(x) {
if (x < 0) {
return ("Enter a positive integer");
}
else {
return (x * fact(x-1))
}
}
}
var result = fact(x)
document.write("The factorial of" + x + "is" + result);
Thanks for the help!
your base case is wrong for a recursive factorial. change it to
function fact(x) {
if (x <= 1) {
return 1
}
else {
return (x * fact(x-1))
}
}
Your definition of factorial is wrong. The traditional recursive definition of factorial is:
F(x) => x == 1 ? 1 : x * F(x-1)
Or you can use the iterative definition
F(x) => var i = 1; for (j = 1..x) i = i * j
In javascript, the recursive version would be:
function factorial (x) {
if (x == 1) return x;
return x * factorial(x-1);
}
The iterative version would be:
function factorial (x) {
var result = 1;
for (var y = 1; y <= x; y++) {
result = result * y;
}
return result;
}
You can add the negative number check in the above functions. But in my opinion that would obscure the purpose of the function (which is to implement the traditional definition of factorial). A better approach is to move the negative number if() check outside of the factorial function. The if (x < 0) check has its own purpose that is separate from calculating factorials: input validation.
In every recursive function, there exists a stopping condition (in your case its if(x<=1)) without which, the function would go to infinite recursion. You had not added that stopping condition. Following is the working updated program:
var x = prompt("Enter a number"); {
function fact(x) {
if (x < 0) {
return ("Enter a positive integer");
}
else if(x <=1){
return 1;
}
else {
return (x * fact(x-1))
}
}
}
var result = fact(x)
document.write("The factorial of " + x + " is " + result);
In addition to fixing the flawed algorithm, I recommend moving your prompt into its own function for separation of concerns.
I also like the idea of using a while statement for this as well as doing a parseInt on the input:
function fact(x) {
while (x > 1) {
return (x * fact(x-1));
}
return x;
}
function doFact() {
var x = parseInt(prompt("Enter a positive integer"));
if (x < 1) {
doFact();
} else {
var result = fact(x);
alert("The factorial of " + x + " is " + result);
}
}
doFact();

setInterval works just one time, then stops

I create a countdown function but it works just at the begining and then stops.
var rek_inter = setInterval(cnt(s_, d), 1000);
function cnt(deg, deg2) {
deg--;
while (deg < 0) {
deg = 59;
deg2--;
}
if (deg2 < 0) {
$('#s_').html("ok");
} else if (deg2 >= 0) {
var d_sn = fixd(deg2);
var s_sn = fixd(deg);
$('#s_').html(d_sn + ":" + s_sn);
}
}
function fixd(g) {
if (g < 10) {
return '0' + g;
}
return g;
}
I tried that, too;
var rek_inter = setInterval(function() {cnt(s_, d);}, 1000);
But result was same.
If I put the function into the interval function like that:
var rek_inter = setInterval(function () {
s_--;
while (s_ < 0) {
s_ = 59;
d--;
}
if (d < 0) {
$('#s_').html("ok");
} else if (d >= 0) {
var d_sn = fixd(d);
var s_sn = fixd(s_);
$('#s_').html(d_sn + ":" + s_sn);
}
}, 1000);
function fixd(g) {
if (g < 10) {
return '0' + g;
}
return g;
}
It works. But I need that as I wrote first at the top. What could be the problem and solution here?
"I have lot of s_, s_2, s_3.... and d, d1, d2... values and I want to use them in single setInterval, this is why I am tryng to use cnt(s_, d); if that will work I will write cnt(s_2, d2), cnt(s_3, d3).."
You could just use closures to your advantage here.
var rek_inter1 = setInterval(cnt(s_2, d2), 1000),
rek_inter2 = setInterval(cnt(s_3, d3), 1000);
function cnt(deg, deg2) {
return function () {
deg--;
while (deg < 0) {
deg = 59;
deg2--;
}
if (deg2 < 0) {
$('#s_').html("ok");
} else if (deg2 >= 0) {
var d_sn = fixd(deg2);
var s_sn = fixd(deg);
$('#s_').html(d_sn + ":" + s_sn);
}
};
}
The first attempt is the same as :
setInterval ( value, time) ;
Here value = cnt(s_, d), the result of the call of the cnt function.
This cannot work, since setInterval expects a function. Too bad it silently fails in javascript.
In the second attempt, the issue is that you modify only function var, so no change can occur : you change deg, deg2, when in fact you would like to change s_ and d.
The third attempt is right, since you both invoke a function and change the globals s_ and d.
I would rather write it this way :
var rek_inter = setInterval( iterate , 1000);
function iterate () {
s_--;
while (s_ < 0) {
s_ = 59;
d--;
}
if (d < 0) {
$('#s_').html("ok");
} else if (d >= 0) {
var d_sn = fixd(d);
var s_sn = fixd(s_);
$('#s_').html(d_sn + ":" + s_sn);
}
}
Edit :
The O.P. mentionned that he wants to handle a set of (s_, d ) parameters.
I suggest you create an array of object which contains such parameters :
var sdParameters = [];
sdParameters.push( { s : some value , d: some other value} );
sdParameters.push( { s : some value 2, d: some other value 2 } );
... // (or using a for loop to grab the ds and ss if possible)
Then after each s/d object is defined by its index, so with :
function iterate (ind) {
var s_ = --sdParameters[ind].s ;
while (s_ < 0) {
s_ = 59;
sdParameters[ind].d--;
}
var d = sdParameters[ind].d;
if (d < 0) {
$('#s_').html("ok");
} else if (d >= 0) {
var d_sn = fixd(d);
var s_sn = fixd(s_);
$('#s_').html(d_sn + ":" + s_sn);
}
}
you can have all your intervals running on one single global array with :
var rek_inter = setInterval( iterate.bind(null,0) , 1000);
var rek_inter1 = setInterval( iterate.bind(null,1) , 1000);
(obviously you can/should store the intervals in an array, you might store them within sdParameters.
One last remark : i couldn't use relevant variable names, since i couldn't guess the use. Using significant names in your code can be of great help when things gets more complex.

Stuck SICP Exercise 1.1.7 in Javascript

I've decided to try working through the MIT SICP course, but in Javascript.
The following code outputs undefined, but it should output a fairly accurate guess of the square root of 5.
I've tested all of the smaller functions and they all work as expected, the problem must be somewhere in the recursive guessRoot() function, but I can't seem to see the problem.
var square = function(x) {
return x * x;
};
var abs = function(x) {
return x > 0 ? x : -x;
};
var goodEnough = function(g, x) {
return abs(square(g) - x) < 0.01;
};
var average = function(x, y) {
return (x + y) / 2;
};
var improve = function(g, x) {
return average(g, (x / g));
};
var guessRoot = function(guess, x) {
if (goodEnough(guess, x)) {
return guess;
} else {
guessRoot(improve(guess, x), x);
}
};
console.log(guessRoot(2.5, 5));
Looks like you're just missing a return in the recursive step.
var guessRoot = function(guess, x) {
if (goodEnough(guess, x)) {
return guess;
} else {
return guessRoot(improve(guess, x), x); // ... here
}
};
http://jsfiddle.net/mattball/TyLsL

Categories

Resources