If I define a new Object in javascript, with var myobject = {} I will have an empty object, as expected. However, I fail to understand the logic behind this. Note that it all works, but I don't get it, more a tease than anything else:
var myobject = {}; // Object{}
myobject[001] = "001"; // Object {1: "001"}, So 001 turns to 1
myobject[0099999] = "0099999"; // Object {1: "001", 99999: "0099999"}
//Last line only makes sense after this one (shortened version)▼
myobject[0023122] = "0023122" // Object {... 9810: "0023122" ...}
I know I can't access those properties with myobject.0023122 since they start with a digit, but I can't by doing this myobject['0023122'] either so I'm assuming that the number 0023122 is transformed to the property with a key 9810 since I can do myobject['9810'] and get the result.
What's fascinating about this is that I can do myobject[99999] and myobject['99999'] so javascript didn't need to reject my key although I lose my leading zeros. I'm not talking about what's wrong and right to do, just what is the reason for the number 0023122 to be converted to 9810 while even 0023123 converts gracefully to 23123 just as 0099999 converts to 99999
I assumed it was too big of a number, that's why I tried with one even bigger.
If you remove the leading zeros, the key becomes "23123"
Javascript supports octal numbers:
Positive octal numbers must begin with 0 (zero) followed by octal digit(s).
0023122 (in octal) is 9810 (in decimal)
So any number that has all digits less than 8, but starts with a 0, will be converted to octal.
If it has an 8 or 9, it will get truncated if it starts with a 0.
091 -> 91
but
071 -> 57
Of course, if you use string keys, nothing to worry about:
myobject["001111"] = "001111"
myobject[001111] = 585
If a number in JS starts with a zero, it's assumed to be octal, which is why the key is converted. myobject[0099999] might actually cause an error as it isn't a valid octal number because it contains 9s (but this may vary depending on browser/interpreter)
In the code myobject[0023122] = "0023122"; the value used as an index for object is evaluated as a integer primitive.
The prefix of 0 causes it to be interpreted as an OctalIntegerLiteral, meaning that 0023122 is evaluated as octal. Had it been 23122 it would be evaluated as an IntegerLiteral. 0x23122 would cause it to be evaluated as a HexIntegerLiteral.
See more here: http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.3
Related
Can someone help understand why my session value changed for a particular value, 03375?
My MVC controller code:
Session["something"] = "03375";
My view js code:
$(function(){
alert(#Session["something"].ToString());
});
Result: js alerts 1789. Why???
It works for other values except. Here is a fiddle https://dotnetfiddle.net/zLdyO8
This has nothing to do with asp.net session. If you do this in your page
console.log(03375);
You will get 1789
Why is this happening ?
Because when browser's javascript runtime sees a number starting with 0 prefix, it thinks it is octal representation of the number. In fact 03375 is the octal equivalent of 1789. So your browser is basically converting the octal value
to it's decimal equivalent and giving you 1789 (browsers usually parse the number to decimal representation)
From mdn,
Note that decimal literals can start with a zero (0) followed by
another decimal digit, but if every digit after the leading 0 is
smaller than 8, the number gets parsed as an octal number.
This means, if you are trying
console.log(09375);
It will print,9375 !!!
To handle your case, the ideal solution is to set the correct type value. For example, if you are passing a numeric value, simply set the numeric value instead of the string version with leading zero..
Session["something"] = "3375";
Or even better
Session["something"] = 3375;
Then in the client side,
alert(#Session["something"]);
If you absolutely want to keep the 0 prefix, while setting the session value, but you want the value as number at client side, you can read it in a string and then use parseInt to convert it to a number type
var r = '#Session["something"].ToString()';
alert(r); // the string with leading 0
var n = parseInt(r);
alert(n); // the number
alert(typeof(n));
Seems like it should be simple but I've been googling my rear-end off and thus far haven't been able to come up with a solution. I think what sets this post apart from a lot of others I've seen is that my input is an integer though it may not be a proper JS number.
I'm trying to write a function that takes an integer (e.g. 0100, 010, 100, 0001) and then outputs the correct base 10 integer.
For example if the function receives 0100 what I want to put out is 100.
So,.. if I knew I was going to receive a 4-digit pseudo-integer say 0100 I could:
function getRealNumber(someNum){
var realNum = parseInt(someNum, 16);
return realNum;
}
getRealNumber(0100);
or:
function getRealNumber(someNum){
var realNum = parseInt(someNum.toString(8));
return realNum;
}
getRealNumber(0100);
I would return 100 but obviously if I received 100 that wouldn't work.
I thought I could first convert the input to a string and then parse it to an integer specifying base 10 like so:
function getRealNumber(someNum){
var someNumString = someNum.toString();
var realNum = parseInt(someNumString, 10);
return realNum;
}
getRealNumber(0100);
but this results in 64.
So I think I'm stuck on determining the format of the received integer (i.e. hex, oct).
Thanks for the help and sorry if I missed something obvious.
You need to provide the pseudo-integer as a string. If you enter a numeric literal, it's parsed by the Javascript compiler into a number before parseInt() ever gets called, and the Javascript compiler treats numbers that begin with 0 as octal. So it should be:
function getRealNumber(someNum){
var realNum = parseInt(someNum, 10);
return realNum;
}
console.log(getRealNumber('0100'));
Integer literals starting with a 0 are considered base-8 or octal numbers, in the same way that integers starting with 0x are considered base-16 or hexadecimal. I don't know if the same happens for integers inside strings.
01 === 1
010 === 8
0100 === 64
...
Try entering 0109. You should get an error -9 is not a valid octal digit-. But to be honest I have never ever worked with octal numbers.
I'm taking a numerical input as an argument and was just trying to account for leading zeroes. But it seems javascript converts the number into octal before I can do anything to the number. The only way to work around it so far is if I pass the number as a string initially but I was hoping there'd be another way to convert it after it is passed? So far tried (using 017 which alerted me to the octal behaviour):
017.toString(10) // 15
parseInt(017,10) // 15
017 + "" //15
new Number(017) //15
new Number('017') //17
parseInt('017', 10) // 17
So given
function(numb) {
if (typeof numb === number) {
// remove leading zeroes and convert to decimal
}
else {
// use parseInt
}
}
'use strict' also doesn't seem to solve this as some older posts have suggested. Any ideas?
If you take "numerical input", you should always definitely guaranteed have a string. There's no input method in this context that I know that returns a Number. Since you receive a string, parseInt(.., 10) will always be sufficient. 017 is only interpreted as octal if written literally as such in source code (or when missing the radix parameter to parseInt).
If for whatever bizarre reason you do end up with a decimal interpreted as octal and you want to reverse-convert the value back to a decimal, it's pretty simple: express the value in octal and re-interpret that as decimal:
var oct = 017; // 15
parseInt(oct.toString(8), 10) // 17
Though because you probably won't know whether the input was or wasn't interpreted as octal originally, this isn't something you should have to do ever.
JavaScript interprets all numbers beginning with a 0, and containing all octal numerals as octals - eg 017 would be an octal but 019 wouldn't be. If you want your number as a decimal then either
1. Omit the leading 0.
2. Carry on using parseInt().
The reason being is that JavaScript uses a few implicit conversions and it picks the most likely case based on the number. It was decided in JavaScript that a leading 0 was the signal that a number is an octal. If you need that leading 0 then you have to accept that rule and use parseInt().
Source
If you type numbers by hand to script then not use leading zeros (which implicity treat number as octal if it is valid octal - if not then treat it as decimal). If you have number as string then just use + operator to cast to (decimal) number.
console.log(+"017")
if (021 < 019) console.log('Paradox');
The strict mode will not allow to use zero prefix
'use strict'
if (021 < 019) console.log('Paradox');
I have a button where in the code behind I add a onclick and I pass a unique ID which will be passed to the js function. The id starts with a 0.
It wasn't working and eventually I figured out that the number, id, it was passing was wrong...
Ie. see this: js fiddle
It works with a ' at the start and end of the number. Just wondering why 013 turns to 11. I did some googling and couldn't find anything...
Cheers
Robin
Edit:
Thanks guys. Yep understand now.
As in this case the 0 at the start has a meaning, here the recipient ID in a mailing list, I will use '013' instead of just 013, i.e. a string. I can then split the values in js as each of the 3 values represents a different id which will always be only 1 character long, i.e. 0-9.
A numeric literal that starts with a 0 is treated as an octal number. So 13 from base 8 is 11 in base 10...
Octal numeric literals have been deprecated, but still work if you are not in strict mode.
(You didn't ask, but) A numeric literal that starts with 0x is treated as hexadecimal.
More info at MDN.
In your demo the parameter is called id, which implies you don't need to do numerical operations on it - if so, just put it in quotes and use it as a string.
If you need to be able to pass a leading zero but still have the number treated as base 10 to do numerical operations on it you can enclose it in quotes to pass it as a string and then convert the string to a number in a way that forces base 10, e.g.:
something('013');
function something(id){
alert(+id); // use unary plus operator to convert
// OR
alert(parseInt(id,10)); // use parseInt() to convert
}
Demo: http://jsfiddle.net/XYa6U/5/
013 is octal, not decimal, it's equal 11 in decimal
You should note that 013 starts with a 0. In Javascript, this causes the number to be considered octal. In general you'll want to use the decimal, and hexadecimal number systems. Occasionally though, octal numbers are useful, as this question shows.
I hope this helps! :)
If the first digit of a number is a zero, parseInt interprets the number as an octal.
You can specify a base of ten like this:
parseInt(numberString, 10)
You could also remove such zeros with a regex like this (the result will be a string):
numberString.replace(/^0+/g, '');
What is the difference between parseInt(string) and Number(string) in JavaScript has been asked previously.
But the answers basically focused on the radix and the ability of parseInt to take a string like "123htg" and turn it into 123.
What I am asking here is if there is any big difference between the returns of Number(...) and parseFloat(...) when you pass it an actual number string with no radix at all.
The internal workings are not that different, as #James Allardic already answered. There is a difference though. Using parseFloat, a (trimmed) string starting with one or more numeric characters followed by alphanumeric characters can convert to a Number, with Number that will not succeed. As in:
parseFloat('3.23abc'); //=> 3.23
Number('3.23abc'); //=> NaN
In both conversions, the input string is trimmed, by the way:
parseFloat(' 3.23abc '); //=> 3.23
Number(' 3.23 '); //=> 3.23
No. Both will result in the internal ToNumber(string) function being called.
From ES5 section 15.7.1 (The Number Constructor Called as a Function):
When Number is called as a function rather than as a constructor, it performs a type conversion...
Returns a Number value (not a Number object) computed by ToNumber(value) if value was supplied, else returns +0.
From ES5 section 15.1.2.3 (parseFloat (string)):
...
If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral (see 9.3.1)
...
And 9.3.1 is the section titled "ToNumber Applied to the String Type", which is what the first quote is referring to when it says ToNumber(value).
Update (see comments)
By calling the Number constructor with the new operator, you will get an instance of the Number object, rather than a numeric literal. For example:
typeof new Number(10); //object
typeof Number(10); //number
This is defined in section 15.7.2 (The Number Constructor):
When Number is called as part of a new expression it is a constructor: it initialises the newly created object.
Not a whole lot of difference, as long as you're sure there's nothing but digits in your string. If there are, Number will return NaN. Another problem that you might get using the Number constructor is that co-workers might think you forgot the new keyword, and add it later on, causing strict comparisons to fail new Number(123) === 123 --> false whereas Number(123) === 123 --> true.
In general, I prefer to leave the Number constructor for what it is, and just use the shortest syntax there is to cast to an int/float: +numString, or use parse*.
When not using new to create a wrapper object for a numerical value, Number is relegated to simply doing type conversion from string to number.
'parseFloat' on the other hand, as you mentioned, can parse a floating point number from any string that starts with a digit, a decimal, or +/-
So, if you're only working with strings that contain only numerical values, Number(x) and parseFloat(x) will result in the same values
Please excuse me posting yet another answer, but I just got here via a Google search and did not find all of the details that I wanted. Running the following code in Node.js:
var vals = ["1", "1.1", "0", "1.1abc", "", " ", null];
for(var i = 0; i < vals.length; i++){
var ifTest = false;
if(vals[i])
{
ifTest = true;
}
console.log("val=" + vals[i] + ", Number()=" + Number(vals[i])+ ", parseFloat()=" + parseFloat(vals[i]) + ", if()=" + ifTest);
}
gives the following output:
val=1, Number()=1, parseFloat()=1, if()=true
val=1.1, Number()=1.1, parseFloat()=1.1, if()=true
val=0, Number()=0, parseFloat()=0, if()=true
val=1.1abc, Number()=NaN, parseFloat()=1.1, if()=true
val=, Number()=0, parseFloat()=NaN, if()=false
val= , Number()=0, parseFloat()=NaN, if()=true
val=null, Number()=0, parseFloat()=NaN, if()=false
Some noteworthy takeaways:
If protecting with an if(val) before trying to convert to number, then parseFloat() will return a number except in the whitespace case.
Number returns a number in all cases except for non-numeric characters aside from white-space.
Please feel free to add any test cases that I may be missing.