Why would we declare a second variable (val) when we can use the parameter of the function as a variable?
Here's how it looks like on codecademy:
var divideByThree = function (number) {
var val = number / 3;
console.log(val);
};
divideByThree(6);
I've made some changes as below:
var divideByThree = function (number) {
number = number / 3;
console.log(number);
};
divideByThree(6);
And it works pretty fine!!
In your example, you do not need to preserve the original value of the parameter. However, you may find it easier to use extra variables in the future for more complicated functions.
Here is an example:
// This function uses the parameter "rawNumber" as a variable, but also uses an extra variable "number"
function TestThis(rawNumber, p) {
// Convert the input (string) to integer
// parseInt returns NaN or integer. Truncates decimals
var number = parseInt(rawNumber);
// Check to see if the result is NaN or is an integer
if (isNaN(number)) {
Log(rawNumber + " is not a number.", p); // Log is my imitation of console.log()
}
// will run if number is type int
else {
if (number > 0 && number <= 100) {
Log(rawNumber + " is a valid number.", p);
} else {
Log(rawNumber + " is not between 1 and 100.", p);
}
}
}
You can see this code working in this Fiddle.
In this function I used an extra variable called "number" in three different places. I didn't have to, but it was easier than typing isNaN(parseInt(rawNumber)) and if(parseInt(rawNumber) > 0 && parseInt(rawNumber) <= 100). Codecademy was probably decided to teach you this way because it is easier to realize you can simplify your code than to realize you can simplify a more complex code through the use of extra variables.
Also, JK Price's answer brings up a readability issue. Simply put, this code is easier to read and understand:
function Example(number) {
var processedNumber = 5/(Math.log(1/number*3.14 - 7));
console.log("Message: " + (processedNumber * 2));
console.log("Message: " + (processedNumber / 10));
}
This code might be a little harder:
function Example(number) {
console.log("Message: " + ((5/(Math.log(1/number*3.14 - 7)) * 2));
console.log("Message: " + ((5/(Math.log(1/number*3.14 - 7)) / 10));
}
Variables are supposed to help the programmer write better and describe a better story. You can't have the same actor play multiple characters! One thing it does is to help keep variables separate.
The variable val in this case helps abstract the logic and most importantly help in debugging. If this was a long script and you saw that number was not what you originally passed it, you might consider it to be an error.
Related
How do I add commas in between the inputs to make the function work?
function square(num) {
var items=str.split("")
return Math.abs(num*num - num2*num2)
}
square(4 2);
You can use
function square(num, num2) {
return Math.abs(num*num - num2*num2);
}
console.log(square(4, 2));
console.log(square(2, 4));
You can use Math absolute function:
function square(num, num2) {
var sq1 = num * num,
sq2 = num2 * num2;
return Math.abs(sq2-sq1);
}
To handle the problem that you didn't include in your question, you can pass a string into the square function, and handle like so:
function square(NUMBERS_STRING) {
var numbers = NUMBERS_STRING.split(" "),
sq1 = numbers[0] * numbers[0],
sq2 = numbers[1] * numbers[1];
return Math.abs(sq2-sq1);
}
Please, don't confused square("4 2") with square(4 2).
The second is not valid javascript.
May be worth pointing out that calling this function "square" may be a bad idea. If someone isn't used to your code and they see this function, are they going to know what it does outright? Maybe diffOfSquares(num, num2)?
My recommendation is to have the real mathematic function that'd be reusable in 99% of use cases:
function square(num, num2) {
num *= num;
num2 *= num2;
return Math.abs(num-num2);
}
And then for your overload call the above. Reason for this is that if something were to ever happen and the underlying logic found in function square(num, num2) required modifying, you would only modify it in one case and not for it plus every other overload. Here's how I'd do it for your current case:
function square(str) {
var items = str.split(" ");
return square(items[0], items[1]);
}
Optionally, but for the sake of reusability, what happens in the future if we get a string where they're pipe delimited? Comma delimited? I wouldn't want to break the code that assumed spacing, so I might modify that function to be:
function square(str, delim = " ") {
var items = str.split(delim);
return square(items[0].trim(), items[1].trim());
}
So if I call it, I could do:
square("4 2", " "); // space delimited
square("4 2"); // space delimited for legacy items
square("4, 2", ","); // comma delimited
square("4|2", "|"); // pipe delimited
I'm currently stuck on a Codewars challenge that I can't get my head around:
Given a string representation of two integers, return the string representation of those integers, e.g. sumStrings('1','2') // => '3'
I've used the following code so far, but it fails on large number test cases as the number is converted into a scientific notation:
function sumStrings(a,b) {
var res = +a + +b;
return res.toString();
}
Any help would be much appreciated.
Edit:
Fiddle example: https://jsfiddle.net/ag1z4x7d/
function sumStrings(a, b) { // sum for any length
function carry(value, index) { // cash & carry
if (!value) { // no value no fun
return; // leave shop
}
this[index] = (this[index] || 0) + value; // add value
if (this[index] > 9) { // carry necessary?
carry.bind(this)(this[index] / 10 | 0, index + 1); // better know this & go on
this[index] %= 10; // remind me later
}
}
var array1 = a.split('').map(Number).reverse(), // split stuff and reverse
array2 = b.split('').map(Number).reverse(); // here as well
array1.forEach(carry, array2); // loop baby, shop every item
return array2.reverse().join(''); // return right ordered sum
}
document.write(sumStrings('999', '9') + '<br>');
document.write(sumStrings('9', '999') + '<br>');
document.write(sumStrings('1', '9999999999999999999999999999999999999999999999999999') + '<br>');
The problem is that in that specific kata (IIRC), the numbers stored in a and b are too large for a regular 32 bit integer, and floating point arithmetic isn't exact. Therefore, your version does not return the correct value:
sumStrings('100000000000000000000', '1')
// returns '100000000000000000000' instead of '100000000000000000001'
You have to make sure that this does not happen. One way is to do an good old-fashioned carry-based addition and stay in the digit/character based world throughout the whole computation:
function sumStrings(a, b) {
var digits_a = a.split('')
var digits_b = b.split('')
...
}
What I'm trying to do:
I have a javascript program that, when a button is clicked, takes in 4 strings from 4 text boxes in a form, and outputs those strings into a formatted textarea.
function testResults(form){
var errorhandle1 = parseInt(document.myForm.Item_Code.value);
var errorhandle2 = parseInt(document.myForm.Item_Cost.value);
var errorhandle3 = parseInt(document.myForm.Quantity.value);
//above variables are for error handling.
var d = " ";
var subtotal = parseInt(form.Item_Cost.value) * parseInt(form.Quantity.value);
var subtotalValue = parseInt(document.myForm.Subtotal.value);
var testVar = "Item Code: " + form.Item_Code.value + d +
"Item Name: " + form.Item_Name.value + d +
"Item Cost: " + form.Item_Cost.value + d +
"Quantity: " + form.Quantity.value + '\n';
document.myForm.myTextarea.value += testVar;
document.myForm.Subtotal.value = parseInt(subtotal) + subtotalValue;
document.myForm.Sales_Tax.value = document.myForm.Subtotal.value * salestax;
document.myForm.Total.value = parseInt(document.myForm.Subtotal.value) + parseFloat(document.myForm.Sales_Tax.value);
}
The above code works just fine, and does exactly what I want it to do for the scope of my program.
try {
if ((isNaN(errorhandle3) == true) || (isNaN(errorhandle2) == true)) {
throw "Error1";
}
} catch (e) {
if (e == "Error1") {
alert("Error! You must enter a number into the qty and cost fields!");
}
}
What I'm trying to accomplish with the try...catch block is simply to make sure that
document.myForm.Item_Code.value
document.myForm.Item_Cost.value
document.myForm.Quantity.value
are actually numbers.
The try...catch statements trigger every time I run the program and doesn't care what I put in the corresponding text boxes. I would greatly appreciate any and all insight on this!
Also: I looked at both of these links and was unable to understand my problem.
javascript parseInt return NaN for empty string
http://www.w3schools.com/jsref/jsref_isnan.asp
Your root problem here is that isNaN() tests to see if the value is NaN. It does not test to see if a string is a proper number. It has some coercion rules to try to deal with strings, but that really isn't what it is designed for.
You can see ways to test if something can be parsed into a valid number here: Validate decimal numbers in JavaScript - IsNumeric()
It's worth reading the detail in the good answers there, but it boils down to something like this which is a bit more than you need, but is general purpose:
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
And, then there's no reason to use exceptions in your code, so you can just do this:
if (!isNumber(errorhandle3) || !(isNumber(errorhandle2)) {
alert("Error! You must enter a number into the qty and cost fields!");
}
Also, in your code, some .Value properties look like maybe they should be .value (lowercase).
In your first code block
var errorhandle2 = parseInt(document.myForm.Item_Cost.Value);
var errorhandle3 = parseInt(document.myForm.Quantity.Value);
You are using Value, which should be value, that's case-sensitive.
By the way, isNaN returns boolean, you don't have to compare with true
I ran into a situation at work today where I needed to write the inverse of a function that I had already written, but I found it inefficient to write the inverse manually because it seems like I would be repeating a lot of my code, and if I were to update the original function I would have to update the inverse with the corresponding changes. The function I am talking about looks something like this:
var f = function(id, str) {
if (id === 0) {
return str.substring(0, 4) + " " + str.substring(4, 8);
} else if (id === 1) {
return str.substring(0, 3) + "/" + str.substring(3, 8);
} else if (id === 2) {
return str.substring(0, 4) + "-" + str.substring(4, 8);
} else if (id == 3) {
return str.substring(0, 3) + "," + str.substring(3, 8);
}
}
So for example f(0, "ABCDEFGH") will return "ABCD EFGH". I need an inverse function that uses the function f(id, str) to come up with inputs from the output. So finverse(formattedStr) should return a dictionary of the corresponding inputs. For example, finverse("ABCD EFGH") should return { id: 0, str: "ABCDEFGH" }. Would it be possible to make use of the existing function f to write this inverse such that even if I were to update the original function with an extra "else if" clause, I wouldn't have to update finverse. In other words I do not want to manually construct finverse with if statements to map the outputs back to the inputs, rather I want to manipulate the original function somehow to come up with an inverse. Is this possible in javascript?
with a slight re-factoring, the task is actually pretty simple. You don't need all those ifs, and actually, ifs run slower than Object property lookup, not to mention them not being sealed-up in a private function somewhere...
we can accomplish a translation ( 1 in, 1+ out) without any flow logic:
// replace all the IF logic with an externally-modifiable logic table:
f.lut=[ [4," "], [3,"/"], [4,"-"], [3,","] ]; //(id=index, 0=pos, 1=char)
// simplify f() using the table to make choices instead of conditionals:
function f(id, str) {
id = f.lut[id];
return str.substring(0, id[0]) + id[1] + str.substring(id[0], 8);
}
// use the same table in reverse to compose an inverse function:
function finverse(s){
return {
id: +f.lut.map(function(A,i){ return A[1]==s.split(/[\w]+/).filter(Boolean)[0] ?
String(i):
""
}).filter(Boolean)[0][0],
str: s.split(/[\W]+/).filter(Boolean).join('')
};
}
// first, test new version of f():
f(0, "ABCDEFGH") // ABCD EFGH
f(1, "ABCDEFGH") // ABC/DEFGH
f(2, "ABCDEFGH") // ABCD-EFGH
f(3, "ABCDEFGH") // ABC,DEFGH
// now, test the inverse:
finverse("ABCD EFGH") //{id:0, str:"ABCDEFGH"}
finverse("ABC/DEFGH") //{id:1, str:"ABCDEFGH"}
finverse("ABCD-EFGH") //{id:2, str:"ABCDEFGH"}
finverse("ABC,DEFGH") //{id:3, str:"ABCDEFGH"}
let us know if this isn't what you were wanting, i wasn't 100% sure...
There is really no way to make it work perfectly. That is impossible to implement with nice speed characteristic. So, I try to give you two ways of solving this problem:
Make global object named fRules with rules which used in f().
fRules = [
{
id: 0,
char: ' ',
insertPosition: 4
},
// ... other rules ...
];
Then you can use fRules in f() simply finding rule with needed id and in fInverse iterating over array of rules and finding good one. Now you don't need to change f(), only fRules();
f.toString() to get text of function and parse function to abstract syntax tree with something. Like inner functions of UglifyJs. Read more here. Then you must manually write some inverser based on your function syntax tree. Ugly idea
How would it be a nice way of handling this?
I already thought on removing the comma and then parsing to float.
Do you know a better/cleaner way?
Thanks
parseFloat( theString.replace(/,/g,'') );
I don't know why no one has suggested this expression-
parseFloat( theString.replace(/[^\d\.]/g,'') );
Removes any non-numeric characters except for periods. You don't need custom functions/loops for this either, that's just overkill.
Nope. Remove the comma.
You can use the string replace method, but not in a one liner as a regexp allows.
while(str.indexOf(',')!=-1)str= str.replace(',','');
parseFloat(str);
Or to make a single expression without a regexp=
return parseFloat(str.split(',').join(''));
I'd use the regexp.
I don't have enough reputation to add a comment, but for anyone wondering on the performance for regex vs split/join, here's a quick fiddle: https://jsfiddle.net/uh3mmgru/
var test = "1,123,214.19";
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var a = parseFloat(test.replace(/,/g,''));
}
var t1 = performance.now();
document.write('Regex took: ' + (t1 - t0) + ' ms');
document.write('<br>')
var t0 = performance.now();
for (var i = 0; i < 1000000; i++)
{
var b = parseFloat(test.split(',').join(''));
}
var t1 = performance.now();
document.write('Split/join took: ' + (t1 - t0) + ' ms');
The results I get are (for 1 million loops each):
Regex: 263.335 ms
Split/join: 1035.875 ms
So I think its safe to say that regex is the way to go in this scenario
Building on the idea from #kennebec, if you want to make sure that the commas are correct, and you don't want to replace commas, you could try something like this:
function myParse(num) {
var n2 = num.split(",")
out = 0
for(var i = 0; i < n2.length; i++) {
out *= 1000;
out += parseFloat(n2[i])
}
return out
}
alert(myParse("1,432,85"));
// Returns 1432085, as the comma is misplaced.
It may not be as fast, but you wanted alternatives :)
What about a simple function to solve most of the common problems?
function getValue(obj) {
Value = parseFloat( $(obj).val().replace(/,/g,'') ).toFixed(2);
return +Value;
}
The above function gets values from fields (using jQuery) assuming the entered values are numeric (I rather validate fields while user is entering data, so I know for sure field content is numeric).
In case of floating point values, if well formatted in the field, the function will return a float point value correctly.
This function is far from complete, but it quickly fix the "," (comma) issue for values entered as 1,234.56 or 1,234,567. It will return valid number as far the content is numeric.
The + (plus) sign in front of the variable Value in the return command is a "dirty trick" used in JavaScript to assure the variable content returned will be numeric.
it is easy to modify the function to other purposes, such as (for instance), convert strings to numeric values taking care of the "," (comma) issue:
function parseValue(str) {
Value = parseFloat( str.replace(/,/g,'') ).toFixed(2);
return +Value;
}
Both operations can even be combined in one function. I.e.:
function parseNumber(item,isField=false) {
Value = (isField) ? parseFloat( $(item).val().replace(/,/g,'') ).toFixed(2) : parseFloat( item.replace(/,/g,'') ).toFixed(2)
return +Value;
}
In such case, if function is called result = parseNumber('12,092.98'); it will parse the value as it is a String. But if called as result = parseNumber('#MyField', true); it will try to obtain the value from '#MyField'.
As I said before, such functions are far from complete, and can be expanded in many ways. One idea is to check the first character of the given parameter (string) and decide based on the string format where to obtain the value to be parsed (if 1st character is = '#' then it is an ID from a DOM object, otherwise, if it begins with a number, it must be a string to be parsed).
Try it... Happy coding.