javascript (nodejs) while loop bug - javascript

running the following code in nodejs cli:
var my_function = function() {
var next_value = 1
, value = undefined
, difference = undefined
, prev_difference = undefined
while ((typeof prev_difference === 'undefined') || (prev_difference > 0)) {
value = next_value
next_value = 2
difference = next_value - value
if (difference > prev_difference) {
throw new Error('Diminishing')
}
prev_difference = 0
}
return next_value
}
for (var i = 0; i< 300; i++) { console.log(i); console.log(my_function()) }
At iteration 282 of the loop I start getting the value '1' instead of '2'. Can't for the life of me understand why. This chunk of code is a reduction from something else I've been working on, hence the seemingly unnecessary if statement within the loop. There are a few ways to change this code such that the execution path does not get screwed up, but I'd like to understand why it's breaking with the current setup.
Also, if you have any tips for tools that could aid me in debugging something like this in the future I would be very grateful. For the most part I used console.log to narrow this down.
node.js version v0.8.6. Running on Mac OSX version 10.7.5.
Thanks

If you take out the IF statement it is gonna be fine, it will return only '2' on every iteration. The variable prev_difference is 'undefined' every time and this seems to cause issues.

Related

Javascript - if-statement with multiple numeric conditions doesn't work

I'm trying to make a simple program in javascript+html. If exp exceeds within a certain range/exceeds a certain number, the level displayed goes up by 1. I've tried to make it show onload, but the level doesn't change no matter what happens to the exp staying at the highest one I've written code for so far.
Javascript:
var exp6 = localStorage.exp6;
var pexp6 = parseInt(exp6);
function char6() {
res.innerHTML = res6;
var lsps = pexp6;
localStorage.setItem("lsp", lsps);
return PrUpdate();
}
var lsp = localStorage.lps;
function PrUpdate() {
if (lsp <= 999) {
lvl.innerHTML = 1;
}
else if (lsp >= 1000 && lsp <= 1999) {
lvl.innerHTML = 2;
}
else if (lsp >= 2000 && lsp <= 2999) {
lvl.innerHTML = 3;
}
else if (lsp >= 3000 && lsp <= 3999) {
lvl.innerHTML = 4;
}
else if (lsp >= 4000 && lsp <= 4999) {
lvl.innerHTML = 5;
}
}
I've also included the setChar() function in the window.onload of the page. I've tried including the function itself in it as well, but whether I add it at the end of the setChar() or in the window.onload the problem stays the same. All other functions work fine, it's just this part that doesn't. I'm also trying to make it generic to fit other 'accounts' I'm trying to make to save myself time. But I just can't make it work.
Edit:
I've figured out why it didn't work, and it was cause I had my localStorage.lsp in the wrong place.
I'm trying to figure out now how to make it so I don't have to refresh the page to get it to appear.
[ Solved my issue :), if unclear by my edit above]
The way you are trying to access values from localstorage is incorrect. This is not valid: localstorage.exp6.
Instead try this: localstorage.getItem('exp6')
See the documentation of Web Storage API for more information

Difficulties getting an if...else statement to work inside a function

I know I am very close, but I can't get the code to return anything but the 'savesTheDay' variable in the else option.I don't think I'm setting up my if....else conditionals properly. I think should be going with the "happy ending" for the if statement (in my case, the savesTheDay variable? Should I not define 'dangerLevel' inside the function since I want it to change? Thanks!
**Edited:
I am trying to get each of the phases to return when I call the assessSituation function. I can only get the saveTheDay message to return, even if the value is outside of the parameters of the condition i.e. assessSituation(1);. I'd expect to get the "Meh. Hard Pass." return value instead of saveTheDay.
Added new code, still isn't running though!**
function assessSituation (dangerLevel, saveTheDay, badExcuse) {
var saveTheDay = "Crime won't stand a chance against me!";
var dangerLevel = dangerLevel;
var badExcuse = "I'm scared, I've never gone up against this many villains";
if (10 < dangerLevel < 50) {
console.log(saveTheDay);
} else if (dangerLevel > 50) {
console.log(badExcuse);
} else
console.log("Meh. Hard Pass.");
}
JavaScript, like many other languages (C/C++, Java, etc.) except Python, does not have support for chaining comparison operators.
10 < dangerLevel < 50
is equivalent to
(10 < dangerLevel /* true or false */) < 50
(true) < 50
// or
(false) < 50
Since false == 0 and true == 1, the result will always be true since 0 and 1 are both less than 50.
To fix your logic, use the && (AND) operator:
if ((10 < dangerLevel) && (dangerLevel < 50))
I think it's only returning saveTheDay because it's the only conditional that is matched.
Your dangerLevel = 10, so dangerLevel is not > 50, and it's not smaller than 10, but it's definitely < 50. If you want another return you can change dangerLevel before if else clause.
Ps: I didn't see that your variable inside your function has the same name of the input. You should choose another name if you want to have both
If you’re passing dangerLevel into the function, you’re overwriting it when you create the dangerLevel variable inside the function. Remove “var dangerLevel = 10” and see if the output you get is what you expect.
you are setting dangerLevel = 10;
it doesn't matter what you pass in, 10 gets populated for dangerLevel, so:
10 will never be > 50
will never be <10
wil always be < 50
which is why you always get savesTheDay
You have two conflicting conditons. (dangerLevel<50) and (dangerLevel<10) so when your code runs with dangerLevel=10 its doesn't know wich one to choose. I suggest you remplace (dangerLevel<50) to (10<=dangerLevel<=50)

Refactoring JavaScript function results

I'm working on a project using Leaflet's Mapping API. Right now, I'm cleaning up my code and there's one section I feel could be made better.
I have it set when the location is found, the location is checked both in accuracy and in bounds:
function checkLocation(position)
{
if(position.accuracy > 100)
{
return 4;
}
else if((position.latlng.lat <= **bound** || position.latlng.lat >= **bound**) || (position.latlng.lng >= **bound** || position.latlng.lng <= **bound**))
{
return 5;
}
return 0;
}
Basically, if the accuracy is too low, I throw an error with error code 4. If the coordinates are outside of where I want them to be, I throw an error with error code 5 (These are to correspond to Leaflet's builtin error codes 1-3 so I can switch on them later). I return 0 just to say there wasn't an error.
This function is called by the locationFound event, which has the following code:
var temp = checkLocation(position);
if(temp != 0)
{
// Handle error code
return;
}
This also works, but I'm not fond of how this looks. What I want is for this bit to only take like two to three lines, preferably without an if statement. I originally had the code for checkLocation in this section, but I thought having it on its own would make for cleaner and more reader-friendly code.
My question is is there any way to improve this bit? I looked into lambda expressions but didn't think it fit and I tried using a Promise, but at that point, I was losing lines trying to cut down on lines. I don't want to code golf the code, but I'm still pretty new to JavaScript and I don't know if there's any way to simplify this while still looking professional. I'm also up for changing the checkLocation function if it means improving the code.
If you refactor to this:
function invalidAccuracy(position) {
return position.accuracy > 100;
}
function outOfBounds(position) {
return (position.latlng.lat <= **bound** || position.latlng.lat >= **bound**) || (position.latlng.lng >= **bound** || position.latlng.lng <= **bound**);
}
You can handle it like this:
function checkLocation(position) {
if(invalidAccuracy(position))
return 4;
if(outOfBounds(position))
return 5;
return 0;
}
You can (if you want) put it in 1 line then:
return invalidAccuracy(position) ? 4:
outOfBounds(position) ? 5 :
0;

Chrome 57 making .data() not function well

This part of an .on("change") event is not working properly when users are working in Chrome 57. This is only a Chrome 57 issue.
The userId variable in the if is set and has a value before it gets to this piece of code.
However, the conditional is not being found true when it should.
But if I am debugging and have a break point set I think on the if and I stop at the break point and linger for a while does this work properly.
This is not affecting everyone using 57.
I've only been able to recreate this issue twice and after debugging, it goes away.
Any idea on what's going on and how to fix it?
I will also note that we are using a very old version of jquery - 1.11.1 and upgrading will not be easy.
var selected = $(this).children("option:selected");
var name = selected.html();
var userId = selected.attr("value");
var personInList;
$("li", "#list1").add("li.person", "#list2").each(function () {
if ($(this).data("userId") == userId) {
personInList = $(this);
return;
}
});
if (userId && userId!= "default" && !personInList) {
//some code that gets triggered that shouldn't because this "if" is turning up true
}
For me, this did the trick:
In the place that the .data() is set, just save the element or the result of data somewhere.
$('#someElem').data('userId', '1234');
var elemData = $('#someElem').data('userId');
window['someUniqueKey'] = elemData;
//or
console.log(elemData);
Then, the call to $('#someElem').data('userId') should return valid data in your event handler.
As to why this happens: I would be very gratefull for an answer. A colleague of mine suggested it might be something with the Garbage Collection in the new Chrome. But if so, it looks like it's a bug in the GC.
I don't know the exact cause, but this seems related to garbage collection.
Also, Chrome has started doing some aggressive Javascript throttling.
https://blog.chromium.org/2017/03/reducing-power-consumption-for.html
https://docs.google.com/document/d/1vCUeGfr2xzZ67SFt2yZjNeaIcXGp2Td6KHN7bI02ySo
https://docs.google.com/document/d/18_sX-KGRaHcV3xe5Xk_l6NNwXoxm-23IOepgMx4OlE4
I have been trying a very hacky fix, but it seems to improve things:
var _oldjQueryData = jQuery.fn.data;
var _chrome57Fix = {};
jQuery.fn.data = function(key, value){
if(key && value) {
var resultElem = _oldjQueryData.call(this, key, value);
var resultData = _oldjQueryData.call(this, key)
var cacheKey = key + '_' + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
_chrome57Fix[cacheKey] = resultData;
return resultElem;
}
return _oldjQueryData.call(this, key);
}
Load this piece of Javascript after jQuery and before you own code.
It should work.
Note that this prevents objects from being garbage collected, therefore it has memory impact.

Why is my Javascript logging Unlogged values to the CodeCademy Console?

This has happened many times and I've just ignored it until now, however it's bugging me because I'm not sure if my code will be correct.
The issue is that when I console.log(TextA) or (TextB) and then put a value into a variable, the console will log the value that I push to the variable.
Example below:
My CodeCademy code is:
var slaying = true;
var youHit = (Math.floor(Math.random() * 2) == 1);
var damageThisRound = Math.floor(Math.random()*5 + 1);
var totalDamage = 0;
while (slaying) {
if (youHit) {
console.log("Congrats, you hit");
} else {
console.log("You were defeated by the dragon");
}
slaying = false;
}
And my console log is:
Congrats, you hit
false
Does this happen to anyone else? is it just an error with the CodeCademy system or is my Javascript not correct?
This is because their interpreter, much like the browser console, evaluates all of the code you put into it and all operations in javascript have a return value. Try this for example:
var y = (foo = 'x');
console.log(y);
The assignment operation has a return value. This becomes more apparent when you use things like eval and new Function to evaluate code, because they will show you the value of the last interpreted line of code, then you see that even do..while statements have a return value. If you change the last line of your while statement, you will see that the last value is logged instead of false.
Here is another example using eval that might demonstrate better:
eval('var foo = 0; i = 0; while( i < 2 ) { i++; foo = i * 9; } ')
Note that I didn't log anything explicitly there, but because foo = i * 9 (where i = 2) was the last line evaluated, you will see 18 in your console. Also note that if I had included var in that statement, you would see 1 instead, because i++ would be the last operation that returned a value (to add to the confusion, var assignments return undefined).

Categories