Always call a function with +1 higher than last call? - javascript

Each time the input_function() is called the argument needs to be one integer higher than the last time it was called. It can't be modified.
In the below example the first iteration works, but on the second it will be called with the argument of 4 which should have been 5.
input_function(1)
input_function(2)
for i in 1..4
input_function(2+i)
# do something here with i
input_function(3+i)
# do something here with i
end
Question
How can I make sure that the argument for input_function() is always one higher than the last time it was called?
The solution can be in any langauge.

You can use a closure to keep the state of the function
var input_function = (function() {
var last_argument = null;
return function(input) {
if (last_argument !== null && input !== last_argument + 1) {
throw new Error('invalid input argument: ' + input)
}
last_argument = input;
console.log('input OK', input);
// do something here?
}
})();
input_function(4);
input_function(5);
input_function(3);

Well, usually I would use static variables for this kind of problem. Unfortunately, Javascript doesn't support it. If you want to do something similar in Javascript, you can recurr to this alternative:
function input_function(n) {
alert(n + count.num);
count.num++;
}
// initialize count number
count.num = 0;
input_function(10); // alert 10
input_function(4); // alert 5
input_function(1); // alert 3
Source: DeluxeBlogTips

Javascript may not support static variables per se but functions in JS are first class objects and therefor they can have properties that can be used like statics. Reworking the above example:
function input_function(n) {
alert(n + input_function.count++);
}
input_function.count = 0;
input_function(10); // alert 10
input_function(4); // alert 5
input_function(1); // alert 3

Related

How can I return the values to use in the first function?

I'm currently working a summer course in programming to learn more while school is on summer break. In one of the assignements, I need to use the given variables to calculate the power of two values. I dont know the values beforehand, as the website generates different values when I try to run the program. I've hit my head against the wall for the whole day so any help nudging me in the right direction is appreciated!! Example of the assignment below.
**function laskuFunktio() {
var luku = noudaArvo("luku");
var eksp = noudaArvo("eksponentti");
console.log("Luku " + luku + " potenssiin " + eksp + " on:");
console.log(laskePotenssi(luku, eksp));
}**
function noudaArvo() {
luku = document.getElementById("luku").value
eksp = document.getElementById("eksponentti").value;
return ???
}
function laskePotenssi() {
if (eksp === 0) {
tulos = 1;
}
var tulos = Math.pow(luku, eksp);
return tulos
}
The first function is predetermined so I cant edit it, but the assignments are made possible without editing it or accessing the HTML files. The return statement was just edited by me to sho where I currently am stuck. Thanks for any help once more!
Look at the way noudaArvo() is called. It accepts a single parameter and expects a return value. The parameter it's passing appears to be the ID of the element it wants the value of. So don't hardcode the IDs in getElementByID(), use a parameter (which your noudaArvo() function header is missing) Return that single value, laskuFunktio() is calling it twice to get both values.
laskePotenssi() needs to accept two parameters. Here's an example of a function with 2 parameters and using them within the function body to return the sum of them. Does this help?
function test(param1, param2){
foobar = param1 + param2;
return foobar;
}
Functions may only return one thing, but it appears you'd like noudaArvo() to return the values of both the base and exponent. This can be done by answering an array ("one thing" that can hold two values).
Your first attempt at laskePotenssi uses the variable telos before declaring it. Make that let declaration first.
This can be done with prettier, more concise code, but I've maintained as much as I could from the OP as instruction.
function noudaArvo() {
luku = document.getElementById("luku").value
eksp = document.getElementById("eksponentti").value;
return [luku, eksp];
}
function laskePotenssi(luku, eksp) {
let tulos;
if (eksp === 0) {
tulos = 1;
} else {
tulos = Math.pow(luku, eksp);
}
return tulos
}
function compute() {
let [luku, eksp] = noudaArvo();
let result = laskePotenssi(luku, eksp)
alert(`the answer is ${result}`)
}
<input id="luku" placeholder="enter base"/>
<input id="eksponentti" placeholder="enter exponent"/>
<button onclick="compute()">Compute</button>

if else preventing loop for passing through object

I am having trouble returning a statement when my RegExp finds no matches :
function ai(message) {
if (username.length < 3) {
username = message;
send_message("Oh, well hello " + username + ", My name is Donald J Trump and i'm a big boy");
} else {
for (i = 0; i <= botChat.length; i++) {
var re = new RegExp(botChat[i][0], "i");
if (re.test(message)) {
var length = botChat[i].length - 1;
var index = Math.ceil(length * Math.random());
var reply = botChat[i][index];
send_message(reply);
}
}
}
}
When I enter a phrase it can correctly match the first line in an array as per the for loop. The issue I'm having is when I try to add an else statement it ceases to loop through my array properly.
I have tried :
else if (re.test(message) === false) {
send_message("i can't be expected to know everything");
}
But it doesn't work, it prevents the loop from looping past botChat[0][0].
I've also tried :
if (send_message().val() == "") {
// ...
}
But every time my code no longer works. Is there a method of adding something to my array that says 'if you don't find a match above, choose this'?
Or just a way of working my code so that the if/else works?
attached is the codepen.
I checked your codepen and the lines 190 and 194 console.log(send_message().val()); seems to be breaking the loop because those lines are throwing an exception since send_message() returns undefined and undefined does not have the .val() method.
Your regular expressions are working fine. I recommend not creating new RegExp objects every iteration, instead, use the one defined in the array if (botChat[i][0].test(message)), the overhead will be less.

How do I add up a number to a properties in my object?

I have an object like this:
var statistics = {
won: 0,
tie: 0,
lost: 0
};
I have a function that adds 1 to won:
var plus1 = function() {
return statistics.won++;
}
I call that function within an if/else statement like this:
plus1();
But it doesn't work. Does anyone have an idea?
It's probably that x++ returns x instead of x+1.
You are looking for
var plus1 = function() {
return ++statistics.won;
}
Looking at your code I don't really see any reason why you would return your result.
I would rewrite the function to simply be
function plus1() {
statistics.won++;
}
When it comes to having it update, I can't see any were in your code where you actually update the html. After you've run plus1(). If I run console.log(statistics) in my Console I can see that statistic.won goes up whenever I win.
As already mentioned in the comment above, if you run wins() after you've run plus1() it will all work.
This is due to to way pre/post incrementation works in JavaScript:
var one = 1;
var two = 1;
// increment `one` FIRST and THEN assign it to `three`.
var three = ++one;
// assign `two` to `four`, THEN increment it
var four = two++;
So in your code, you're assigning the value of statistics.won to the return value first and then incrementing it. You can see the difference in how they work here.
So, as I mentioned in the comments, return ++statistics.won; is the solution you need.

keep add the value without overwrite the function

function checkData() {
var temp = 0;
var totalMarks = countMark(temp);
if (totalMarks != 100)
window.alert("Marks must total 100");
}
function countMark(mark) {
var totalMark = 0;
totalMark += parseInt(mark)
return totalMark;
}
function doAdd() {
var taskid = document.getElementById("taskid").value;
var taskname = document.getElementById("taskname").value;
var taskmark = document.getElementById("taskmark").value;
if (taskid.length === 0)
window.alert("Task Id cannot be empty!");
if (taskname.length === 0)
window.alert("Task name cannot be empty!");
if (taskmark.length === 0)
window.alert("Task Mark cannot be empty!");
else if (!markpattern.test(taskmark))
window.alert("Invalid data in mark field");
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
}
My question is when i keep call the doAdd() function. my marks will keep adding . want to do like passing reference like in C++ . my function countMark(...) will keep adding .
after that, when my form submitted, my form will call the function checkData()
If my totalmark is not 100 . will prompt out the alert and error.
but my code is not working . I guess that my countMark function wrong somewhere
If I understand you correctly, you're looking for the equivalent of a static variable - something that gets initialized the first time the function is called, and keeps it's value for subsequent calls.
Take a look at this related question: https://stackoverflow.com/a/1535650/2444111
The top answer (by CMS) is talking about class-based static variables, which are not quite the same thing.
The second answer (by Pascal MARTIN) is what you're looking for. It takes advantage of the fact that JS functions are also objects, and stores the variable as a property of the function object. This is a better solution than using a global variable (or a property of window, which is what a global actually is)
There are several issues in your code and it's really hard to say what your intention was. But I will address what I found.
In the following piece of code you are requesting a DOM Element and try to parse it as an Integer. The result of that type convertion is always NaN. Maybe wanted to get the value attribute of your element, like you did before. (Also, don't request the same element multiple times. Request it once, save the result in a variable and use that variable from that on).
var marks = parseInt(document.getElementById("taskmark"));
if (marks < 0 || marks > 100)
window.alert("Marks out of range. Please re-enter");
countMark(marks);
Your function countMark is pretty useless, because it will always return whatever Number you pass to it (see comments in your code).
function countMark(mark) {
var totalMark = 0; //create a new variable with value 0
totalMark += parseInt(mark) //add "mark" to that variable
return totalMark; //return that variable => 0 + mark = mark (and if mark = NaN => 0 + mark = NaN)
}
Maybe you wanted to make totalMark a global variable, than you would need to define it outside of your function:
var totalMark = 0;
function countMark(mark) {
totalMark += parseInt(mark);
return totalMark;
}
Last but not least, lets analyse your function checkData:
function checkData() {
var temp = 0; //create a local variable with value 0
var totalMarks = countMark(temp); //pass 0 to countMark => return 0 => totalMarks = 0
if (totalMarks != 100) //always true since totalMarks is always 0
window.alert("Marks must total 100"); //will always alert
}

Why does this JQuery only work if I console.log a bad variable? [duplicate]

This question already has answers here:
Why does this append only work if I console log a bad variable
(2 answers)
Closed 9 years ago.
I am relatively new with jquery, and am trying to change an up and down arrow on a js accordion on each click, unfortunately, I have run into an error where it only works if I console.log a bad variable. Does anyone have any guidance as to what I might be doing wrong when I onclick="embiggen(1)" for example if its accordion id one?
There are some other issues surrounding the html, but specifically why is this only working if I console.log;?
function arrowup(id){
$('#downarrow'+id).remove();
$('#dropdown'+id).append('</a>');
$('#dropdown'+id).append('<i id="uparrow'+ id +'" class="icon-1 icon-chevron-up">');
}
function arrowdown(id){
$('#uparrow'+id).remove();
$('#dropdown'+id).append('</a>');
$('#dropdown'+id).append('<i id="downarrow'+ id +'" class="icon-1 icon-chevron-down">');
}
//Switches the arrows
function embiggen(id){
var up = $('#uparrow'+id).length;
if (up == 1){
arrowdown(id);
console.log(i see you);
}
var down = $('#downarrow'+id).length;
if (down == 1){
arrowup(id);
}
}
The bad console.log() makes it "work" because the error breaks the script execution before entering the second if statement.
Fixing the real issue
down == 1 is always true. You should use an else statement:
if ($('#uparrow'+id).length){
arrowdown(id);
} else if ($('#downarrow'+id).length){
arrowup(id);
}
Understanding it
down == 1 is always true independently of up == 1. Here's your logic explained in pseudo-code in both scenarios:
var up = 1, down = 0;
if (up) { down = 1; up = 0; } //enters this block, down now is 1
if (down) { down = 0; up = 1; } //enters this block as down == 1
var up = 0, down = 1;
if (up) { down = 1; up = 0; } //doesn't enter this block
if (down) { down = 0; up = 1; } //enters this block as down == 1
You just have put an else in there so the execution flow does not enter the second if statement in case the first one succeeds.
if (up) {}
else if (down) {}
Truthy/Falsy values
To explain why I'm using .length isolated inside the conditional statement: in JavaScript, the number 0 is a falsy value and 1 is truthy, hence these can be used directly inside the if statement and it will be interpreted based on the internal ToBoolean algorithm logic. Obviously you can == 1 if you feel like, that's more clear though slightly redundant.
A possibly simpler way around
Going a little off-topic, but your goal can most likely be achieved in an easier way. I may be oversimplifying your logic, but depending on your intents you may just toggle between those two classes:
function embiggen(id) {
$('#arrow'+id).toggleClass('icon-chevron-up icon-chevron-down');
}
Then, you'd no longer have to create a new #downarrow/#uparrow element each time the function is called. If said arrow has JS behavior attached, you can check which logic to execute through an if statement using hasClass().
It works because when an error occurs, JavaScript skips the rest of your function body.
The problem in your case is that the function arrowdown() creates #downarrow+id, making the next condition truthy and calling the function arrowup().
You either need an alternative branch, using Fabricio's answer, or return immediately after making changes to the DOM that would otherwise change the state:
function embiggen(id) {
if ($('#uparrow'+id).length) {
return arrowdown(id);
}
if ($('#downarrow'+id).length) {
return arrowup(id);
}
// ehm, something else happened?
}

Categories

Resources