I have the following problem:
I was trying, inside a common HTML page mixed with some Javascript, to write a simple program so that a specific div would be filled with the result of a function.
The result of the function consists of a string of text, below a row of dashes with as many dashes as the number of characters inside the text string.
My code is as follows, inside the body:
<div id="div1"></div>
<script>
let tab = "";
function result(text) {
for (i in text) {
tab += '-';
}
return "<p>" + tab + "<br>" + text + "</p>";
}
document.getElementById("div1").innerHTML = result("Bear") + result("Bear") + result("Bear");
</script>
The rendered HTML returns the following result:
Only the first invocation of the function works as expected: 4 dashes for 4 letters. But the second invocation renders twice as many dashes, and the third one three times as many.
Perhaps "return" is not the command to use?
You only set tab to an empty string at the start of the program.
You don't set it to an empty string inside the function.
So it never gets reset to an empty string.
Every time you call the function, tab just gets dashes added to whatever is there.
If you want to reset it every time the function is called, then reset it inside the function.
It waa already answered. Still a different view could help:
Issue &. Fix
Each call of result(text) is adding dashes to the global variable tab (here 3 times the same length: 4 + 4 + 4).
Usually let keyword is described with following:
declare a scoped variable, which is only valid and has a lifetime within the current [scope] (here: for the whole script, not only inside the function).
Commented and properly formatted (proper indentation eases readability!) your script:
let tab = ""; // declared at start of the script, means global scope
function result(text) {
// move declaration here so it always is reborn (local scope = new lifetime)
for (i in text) {
tab += '-';
}
return "<p>" + tab + "<br>" + text + "</p>";
}
From your described intend scoped should rather be declared inside the function. So it has local scope (known inside the function only).
Moreover it will automatically be reset at each call of the function.
Alternative
In old console usage (Text-UI) and still in ASCII-Art the basic method to draw a textual line with any character like dashes - was described either of:
fill width of n characters with character a
return string which contains character a repeated for n times
So they invented functions like fillString( a, n ) or a.repeat( n ).
Similar can be done in JavaScript.
Benefits:
you can parameterize the filler character, e.g to = or _
you can easily reuse this generic function
Bonus: Review
My experience taught me to pay attention to naming in code.
Express intend and purpose, so you and everybody else can see now – and in 6 months – the mraning of variables and functions at a glance.
most functions return a result, this does more: function addSameWidthLineAbove(text)
let line or textualBorder or dashes
Related
I am trying to learn js basics.
I tried analysing the string count code but I am not sure about certain statements.
can you guys tell me why it's behaving in such a way?
this will help to understand better and in future, I can fix the issues by myself.
providing code below
String.prototype.count=function(c) {
var result = 0;
var i = 0;
console.log("this--->" + this); // how come this prints strings here, since we dont pass stings here
console.log("this.length--->" + this.length);
for(i;i<this.length;i++)
{
console.log("this[i]--->" + this[i]); // here we did not declare this an array anywhere right then how come its taking this[i] as s and stings also we did not put in any array
console.log("c--->" + c);
if(this[i]==c)
{
result++;
console.log("inside if result++ ---->" + result++);
// here it prints 1 and 3 but only two times s is present so it should print 1 and 2 right
}
}
console.log("out of for loop result--->" + result);
// how its printing 4 but s is present only two times
return result;
//console.log("out of for loop result--->" + result);
};
console.log("strings".count("s")); //2
output
this--->strings
this.length--->7
this[i]--->s
c--->s
inside if result++ ---->1
this[i]--->t
c--->s
this[i]--->r
c--->s
this[i]--->i
c--->s
this[i]--->n
c--->s
this[i]--->g
c--->s
this[i]--->s
c--->s
inside if result++ ---->3
out of for loop result--->4
4
Questions from your code example are basicly about 2 issues:
this - is JS keyword. You don't have to initialize it, it automatically defined everytime, everywhere in your JS code. And it could mean different things in different situations, but it's too advanced topic if you've just started learning JS. For now lets just say, that this refers to the context, that called count() function, which is the string "strings". So it has length and you can iterate over it as an array of characters
Why the count rose to number 4, when it should be 2? Because when you found a match between current letter of the string and the character "s" (line with this[i]==c) you increment the result by 1 using result++. But you do it also in your console.log right after it, so it gets increased by 2 every time it finds a match
console.log("this--->" + this); // how come this prints strings here, since we dont pass stings here
That prints a string because you have a string + something. This is called string concatenation and the result of string concatenation is a string. In this case, this is the object that called the count function which was a string.
console.log("this[i]--->" + this[i]); // here we did not declare this an array anywhere right then how come its taking this[i] as s and stings also we did not put in any array
this is a string. Bracket notation on a string will return the char at the provided index.
result++;
console.log("inside if result++ ---->" + result++);
// here it prints 1 and 3 but only two times s is present so it should print 1 and 2 right
the result++ notation is the same as result += 1, but result++ does the addition of 1 AFTER the value is evaluated while ++result will do it before. So in this example the order of events is:
add 1 to the result, then print the console.log, then add 1 to the result
Hope that helps!
This is what I am doing: I am building a fun in house API Voting System. I am using a client side snippet insert onto page
Like this:
<script src="domain.com/api/scripts/main.js"></script>
<div id="content-wrap" id="ac1e435e-c564-48f8-9f45-338616e7a789"></div>
Now in my main .JS I do all ajax request and modify the #content-wrap with creating new elements and inserting additional JS required to run Voting System.
However big issue I am experiencing is when I write JavaScript that I need to insert into #content-wrap I am currently writing it like this:
script.innerHTML = "$(someting).on('click', funciton(){"
+ "$.ajax({type: 'post',"
+ " url: '" + base + "/api/request', data: $('form').serialize(), "
+ "success: function(response){";
As you can see that can cause lot of issues as I build on it.
What is better way to accomplish this or is there a way i can just write my script / code and do something like this.
script.innerHTML = ConvertToString(script.js) OR ConvertToString(function X);
ConvertToString is just an expression I am using to explain what I would like to do instead of what I am doing.
Thank you, I am open to any suggestions.
I also must do this in plain JavaScript or with jQuery library so any suggestions to use VueJs, AngularJS or React will be considered as future references.
Thank you again
Additional explanation:
I would like to insert into my script element JavaScript snippet. But my snippet is about 30 lines long currently and might get bigger with time so it is very difficult to code with all the + " code " on every line that I write so that it can be inserted with innerHTML into element and executed on Client end.
So I would instead like to do something like this
element.innerHTML = mysnippetcode // but with out using + "" on each line like shown above
OR
element.append(snippet)
I hope this makes it little more clear
Solution that worked for me was using back ticks to wrap my sinppet and insert it into innerHTML of the element..
Just use the function's name without the () to convert it to a string:
function foo() {
var a = 10;
var b = 20;
var c = a + b;
return c;
}
document.write(foo);
The document.write will result in this string:
function foo() { var a = 10; var b = 20; var c = a + b; return c; }
If you only want the function's body, then you could just normally remove the first and last characters of the string.
I am not entirely sure this is what you wanted, if not, please make yourself more clear.
Alternatively, you could do an eval([insert function code here]) and there would be no need to add the code to the innterHTML of the script, read up on that function if you haven't heard of it.
Or if you want to create a function from a string, you can use new Function([name] ,[function body string]) if you need arguments you have to sandwich them between the 2 parameters.
But my snippet is about 30 lines long currently and might get bigger with time > so it is very difficult to code with all the + " code " on every line that I
write
You can use template literals if you want multi-line strings in Javascript, you simply have to replace your quotes with backticks.
See this MDN page if you are interested, or even this StackOverflow answer.
I'd like to ask wether there is a way to evaluate javascript terms multiple times without needing to parse a term over and over and over again.
Say, you want to evaluate
var1/var2+Math.sqrt(var3)
20 times a second.
This could be problematic when using
ScriptEngine.eval(string)
continueously, because you would have to replace "var1" every single time, then parse it and then let the script engine figure out the order of operations you want to perform.
Is there any alternative way?
Say, you have a configuration file in which a user gets to specify variables which increase and decrease after certain events.
You have a fixed term which javascript needs to process and the user also gets to define, but the variables change.
So is there a way to save a term as a list of operations (which internally speaking, it is) into which you only need to input the variables?
So basically, is there a way around parsing and creating an operation order over and over?
You could evaluate the expression wrapped in a function:
var expression = "var1/var2+Math.sqrt(var3)";
eval( 'function myTest(var1,var2,var3){ return ' + expression + "}" );
console.log(myTest, myTest(1, 2, 9) );
I think you are looking for a for loop.
var x = //number of time you want to run
for (i = 0; i < x; i++) {
//code...
}
or a while loop
while (condition is true) {
//code...
}
Just switch out the variables as needed to adjust how long the process runs. Or really anything else you need to adjust.
var reset = function ()
{
var p = parseFloat($("#IA").val());
var q = parseFloat($("#IB").val());
var m = parseFloat($("#CGCD").val());
var aR = [];
aR += ["GCD(" + p + "," + q + ")=" + m];
document.getElementById("PGCD").innerHTML = aR + "\n";
document.getElementById("IA-error").innerHTML="";
document.getElementById("IB-error").innerHTML="";
$("#IA").focus();
};
The code above is only for a 'reset' function, a part of additional code (not present), the purpose which is to find the Greatest Common Denominator, GCD.
My 'reset' function is connected to a button, #reset, the purpose of which is to do four things:
add and store the string GCD(p,q)=m to the array 'aR'; p/q/m are variable stand-ins for the values of the input text areas #IA, #IB, and #CGCD (the GCD of #IA and #IB);
display the array 'aR' in a text-area #PGCD each time the reset button is clicked; this is why I used an array;
clear the two input text areas #IA and #IB;
clear the one output text area;
As it stands, all four objectives are completed successfully, with one exception: for the second objective, only the most recent GCD calculation is outputted; none of the previous calculations output.
I cannot get the array to list the different saved calculations within it. I think (?) the new calculations are being added to the array, but I am not sure.
I've tried a 'for' statement, and an 'if' statement, neither of which worked. I don't know whether I coded it wrong, or if it wasn't the right solution for my issue.
I tried to search the forums (here) for a solution, but was unable to find one.
Thank you.
If I'm understanding what you are describing, I believe your problem is that you are attempting to use += to add elements to an array. You should use
aR.push("GCD(" + p + "," + q + ")=" + m);
The += operator is used for addition of a value to itself as well as string concatenation.
Edit: per comments below, the main issue was declaration of aR as a local variable. It needs to be either global or declared within the same scope.
I always see a write style in javascript but I don't know why code like this.
For example, I have a variable.
var topic = "community";
And when I learned javascript I saw someone coded in jQuery like this, some code in section.
:contains("' + topic + '")
But I think it can code just like this.
:contains(topic)
Or
:contains("topic")
What the differences between above three ?
:contains("topic")
this search for elements that contains "topic" string
where as
var topic = "community";
:contains(topic)
topic here becomes "community"..so it searchs for element that contains "community";
well for this
:contains("' + topic + '")
i guess the code is incomplete..
$('div:contains("' + topic + '")')..; //div for example sake
this becomes
$('div:contains("community")')..; //<-- just to make sure the string is encoded with `""`
:contains("' + topic + '") will look for the string '(VALUE of topic)', including the single quotes.
:contains(topic)
will look for the value of topic, with no surrounding quotes.
:contains("topic")
will look for literally topic.
There is no difference between single quotes and double quotes, both are used to mark an element as a string.
var s = "hello"
var m = 'hello'
m === s // true
the other example refers to escaping a string, in the case of:
contains("' + topic + '")
topic actually references a variable and not a string, therefore the quotes must be escaped in order for the program to get access to the value of the variable. otherwise it would not read the value of the variable topic but simply print the string "topic".
Single quotes vs double quotes usually has to do with whether or not string replacement will happen, but in JS it doesn't matter as far as I know
the difference between the 3 is that the first one is a variable assignment where string replacement can happen. the second one is passing a string as an argument and the third one is passing the variable or constant topic
var topicOne = "Community1";
function write(toOutput) {
document.write(toOutput);
}
write(topicOne);
write("topicOne");
write('topicOne');
so here is what the 3 will output:
Community1
topicOne
topicOne
In PHP however the same code will act differently because the double quote implies string replacement
<?php
$topicOne = "community1";
$topicTwo = "community2$topicOne";
function write($toOutput) {
print $toOutput;
}
write($topicOne);
write("$topicOne");
write('$topicOne');
write($topicTwo);
write("$topicTwo");
write('$topicTwo');
?>
will produce a different output
community1
community1
$topicOne
community2community1
community2community1
$topicTwo
see where the difference is?