I'm just trying to understand how JS currying works. While I was looking for it I found a related example:
var add = function (orig) {
var inner = function (val) {
return add(parseInt(val+'', 10) == val ? inner.captured+val : inner.captured);
};
inner.captured = orig;
inner.valueOf = function () {return inner.captured;};
return inner;
};
What the point to add an empty string to the first argument in a parseInt
method?
I think it also can be related to the valueOf
val+'' converts expression to string.
Quick test to show what's going on:
typeof(1)
"number" // value is 1 (number)
typeof(1+'')
"string" // now value is "1" (a string)
what is the purpose of making it a string?
The purpose could be to avoid native code to call abstract ToString method to convert first argument of parseInt to string.
We can read in MDN that first argument to parseInt is string with following description:
The value to parse. If string is not a string, then it is converted to
a string (using the ToString abstract operation). Leading whitespace
in the string is ignored.
To explain we can re-write part of the code:
return add(parseInt(val+'', 10) == val ? inner.captured+val : inner.captured);
// could be written like:
if ( parseInt(val+'', 10) == val ) {
return inner.captured+val
}
else {
return inner.captured;
}
// Looking at:
parseInt(val+'', 10) == val
// we're checking if the number at base 10 is equal to itself
// parseInt takes a string as it's first parameter, hence
// the type-casting with +''.
// This step could probably be ignored as the docs say that the number is
// cast to a string automatically, however for completeness we might
// choose to manually cast it.
parseInt docs
Related
I store some parameters client-side in HTML and then need to compare them as integers. Unfortunately I have come across a serious bug that I cannot explain. The bug seems to be that my JS reads parameters as strings rather than integers, causing my integer comparisons to fail.
I have generated a small example of the error, which I also can't explain. The following returns 'true' when run:
console.log("2" > "10")
Parse the string into an integer using parseInt:
javascript:alert(parseInt("2", 10)>parseInt("10", 10))
Checking that strings are integers is separate to comparing if one is greater or lesser than another. You should always compare number with number and string with string as the algorithm for dealing with mixed types not easy to remember.
'00100' < '1' // true
as they are both strings so only the first zero of '00100' is compared to '1' and because it's charCode is lower, it evaluates as lower.
However:
'00100' < 1 // false
as the RHS is a number, the LHS is converted to number before the comparision.
A simple integer check is:
function isInt(n) {
return /^[+-]?\d+$/.test(n);
}
It doesn't matter if n is a number or integer, it will be converted to a string before the test.
If you really care about performance, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
return function(n) {
return re.test(n);
}
}());
Noting that numbers like 1.0 will return false. If you want to count such numbers as integers too, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
var re2 = /\.0+$/;
return function(n) {
return re.test((''+ n).replace(re2,''));
}
}());
Once that test is passed, converting to number for comparison can use a number of methods. I don't like parseInt() because it will truncate floats to make them look like ints, so all the following will be "equal":
parseInt(2.9) == parseInt('002',10) == parseInt('2wewe')
and so on.
Once numbers are tested as integers, you can use the unary + operator to convert them to numbers in the comparision:
if (isInt(a) && isInt(b)) {
if (+a < +b) {
// a and b are integers and a is less than b
}
}
Other methods are:
Number(a); // liked by some because it's clear what is happening
a * 1 // Not really obvious but it works, I don't like it
Comparing Numbers to String Equivalents Without Using parseInt
console.log(Number('2') > Number('10'));
console.log( ('2'/1) > ('10'/1) );
var item = { id: 998 }, id = '998';
var isEqual = (item.id.toString() === id.toString());
isEqual;
use parseInt and compare like below:
javascript:alert(parseInt("2")>parseInt("10"))
Always remember when we compare two strings.
the comparison happens on chacracter basis.
so '2' > '12' is true because the comparison will happen as
'2' > '1' and in alphabetical way '2' is always greater than '1' as unicode.
SO it will comeout true.
I hope this helps.
You can use Number() function also since it converts the object argument to a number that represents the object's value.
Eg: javascript:alert( Number("2") > Number("10"))
+ operator will coerce the string to a number.
console.log( +"2" > +"10" )
The answer is simple. Just divide string by 1.
Examples:
"2" > "10" - true
but
"2"/1 > "10"/1 - false
Also you can check if string value really is number:
!isNaN("1"/1) - true (number)
!isNaN("1a"/1) - false (string)
!isNaN("01"/1) - true (number)
!isNaN(" 1"/1) - true (number)
!isNaN(" 1abc"/1) - false (string)
But
!isNaN(""/1) - true (but string)
Solution
number !== "" && !isNaN(number/1)
The alert() wants to display a string, so it will interpret "2">"10" as a string.
Use the following:
var greater = parseInt("2") > parseInt("10");
alert("Is greater than? " + greater);
var less = parseInt("2") < parseInt("10");
alert("Is less than? " + less);
I'm trying to solve the following problem:
Complete the solution so that it returns true if the first argument (string) passed in ends with the 2nd argument (also a string).
Examples:
Solution ('abc', 'bc') // returns true,
solution ('abc', 'd') // returns false
Create a function that does this.
My code is:
function solution(str, ending){
return (str.split('').filter(str => str.length > str.length - 2).join('')) == ending ? "true" : "false"
}
The error I get:
expected 'false' to equal true
Some issues:
You have used the name str for the function parameter and for the parameter in the filter callback function. So in that callback function you'll have no access to the original str value.
In the filter callback, str will be a single character, so its length will always be 1. It makes no sense to compare it with anything
If you go with filter, then you'd want to do something with the index of the character, not the character itself.
In this problem the value 2 has no special meaning, it should not need to occur anywhere in your code
The function returns a string "true" or "false", but you are required to return a boolean value (true or false). Those are not strings.
Using the conditional (ternary) operator just to return a boolean is overkill: just return the boolean expression that serves for the condition.
The whole idea of using filter is not necessary as there is endsWith
I guess you wanted to do something like this:
function solution(str, ending){
return str.split('').filter((_, i) => i >= str.length - ending.length).join('') == ending ? true : false;
}
console.log(solution("longword", "word"));
But it can be as simple as:
function solution(str, ending){
return str.endsWith(ending);
}
console.log(solution("longword", "word"));
This has become more of a pondering about how javascript works, than an actual problem to fix. In the case of a statement like
var str = 9 + " some words here";
The resultant str var would contain the value "9 some words here". My question is what function does javascript use to automatically coerce the Number object '9' into a string to be concatenated with the String object " some words here", and is this function changeable/overrideable.
This started from me needing to output single digits with a preceding 0 on a page. This was easy enough to accomplish with a quick prototype function on the Number object
Number.prototype.SpecialFormat = function() {
if(this < 10) {
return "0" + this;
}
else {
return this.toString();
}
};
And call it with a simple (9).SpecialFormat() + " words here";
But that got me wondering if I could overwrite the toString function on a Number with a
Number.prototype.toString = function() {
if(this < 10) {
return "0" + this;
}
else {
return this;
}
};
, and just let javascripts automatic conversion handle it for me, so I could use a standard 9 + " words here"; to get the same result "09 words here". This did not just implicitly work, I had to end up adding .toString to the 9 (9).toString() + " words here" (which upon taking a further look, would have resulted in some infinite loops).
So is there a way to override the built in functionality of a javascript native type ?
*Note: I realize this is likely a 'worst idea ever'
The addition operator coerces its arguments to strings in step 7:
If Type(lprim) is String or Type(rprim) is String, then
Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
The ToString operation has special rules for numbers, detailed under "ToString Applied to the Number Type".
It appears that the abstract operation ToString(number) does not ever use Number.prototype.toString. In fact, ti's the other way around: the default Number.prototype.toString function employs the abstract numeric ToString algorithm. Thus, it's not possible to override the default behavior for the stringification of numbers during type coercion in ECMAScript 5, because there's no way to alter the language-defined ToString operation.
ToString does use the target's toString method when coercing objects to strings, but not number primitive values.
(not strictly an answer but I need some space)
Be very careful with type coercion, especially when combining primitive types with their object counterparts because:
var n = 9;
typeof n; // "number"
n instanceof Number; // false!!
n = new Number(9);
n instanceof Number; // true, oh thank God
typeof n; // "object" what!!
Also, toString on Number doesn't actually work:
Number.prototype.toString = function () { return "foo" + this; };
var n = new Number(9);
"" + n; // "9", not "foo9"
A way to avoid this mess is by having:
var ns = {
number: {
specialFormat: function () /* .. */ }
}
}
ns.number.specialFormat(9); // "09"
I have the following code in an external javascript file. I am getting an error on this line below: guessNum = inGuess.parseInt();
firebug tells me the parseInt is not a function. I thought all things in js were basically objects (at least that is what I remember reading in W3School). I am sure this is something simple, I am just stuck. Any suggestions are welcome. Thanks
function inputNum()
{
/* initialize variables */
var inGuess = "";
var loopCt;
var guessResult = "";
var correctNum = 26;
var guessNum = 0;
for (loopCt=1;loopCt<11;loopCt++)
{
inGuess = prompt("Please enter your guess(enter -1 to exit) Do not press Enter","0");
if (inGuess == "-1") { break; }
if (inGuess==null || inGuess=="")
{
alert("Blanks are not allowed. To exit enter '-1'.");
}
else
{
guessNum = inGuess.parseInt();
if (inGuess == "26")
{
alert("Congratulations, you guess correctly!");
guessResult="Correct!";
}
else
if (guessNum < correctNum)
{
guessResult="Too low";
}
else
{
guessResult="Too high";
}
document.getElementById('emp'+loopCt).innerHTML=inGuess;
document.getElementById('ct'+loopCt).innerHTML=guessResult;
}
}
}
parseInt is a global function. You are trying to access it off of a string object, where it doesn't exist.
guessNum = parseInt(inGuess, 10); // Tell it what base to use. Protect against 08 being interpretued as octal.
That would be the correct way to handle this.
parseInt Mozilla Developer Network Docs
Footnote - parseInt can return NaN which when compared with typeof actually returns number
parseInt is a method on window, not on a string. You want
guessNum = parseInt(inGuess, 10);
The second argument insures that your code will treat the first argument as a base-10 number, meaning it will correctly parse "010" as 10 and reject "0x10" instead of parsing it as 16.
I thought all things in js were basically objects
They are objects, but that doesn't mean that all objects have the same set of methods defined on them.
If you do want to use it like that for whatever exotic reason, you can define prototype on the String object:
String.prototype.parseInt = function() {
return parseInt(this,10);
}
var inGuess = "26";
alert(inGuess.parseInt());
Your syntax isn't quite right... From the console:
> x = parseInt("2", 10)
2
Also, something to keep in mind, which come from the docs...
If the input string begins with "0", radix is eight (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 specifies that 10 (decimal) is used, but not all browsers support this yet. For this reason always specify a radix when using parseInt.
parseInt() Documentation
inGuess is a string and string does not have parseInt function. parseInt is a global function.
do this:
guessNum = parseInt(inGuess);
I was looking into Raphael JS library but I see this:
Animation.prototype.delay = function (delay) {
var a = new Animation(this.anim, this.ms);
a.times = this.times;
a.del = +delay || 0;
return a;
};
What is the + operator before the delay variable?
Thanks.
It converts a String variable to a Number, if possible: +'21.2' equals Number(21.2). If the conversion fails, it return NaN (that's where || 0 kicks in in your example code)
It is a way to make a variable value to number, if the variable has a number. alternative you can use Number function.
It is a Unary Operator. It converts/parses numbers from a string, boolean or even null values.
It can:
Parse a number from a string, so +"23" returns 23
Parse +True/+False to 1 or 0 respectively.
even +null would return 0.
You can, of course, perform Math.* functions on these above-mentioned returns.
eg.
let str = "25.5";
Math.ceil(+str) // would return 26
I hope this helps!