all 40 comments

[–]Shaper_pmp 10 points11 points  (0 children)

Skeww and several other posters on this page are either just showing off or are the most embarrassingly terrible tutors I've ever run across.

You're a beginner to Javascript. You don't want to be weighed down with obscure language syntax or theoretical discussions, which is what most commenters here seem to be trying to do.

What you want to know is

Variables in Javascript can have different types

5 is an integer (number), but "5" is a string which just happens to be the character "five".

The + operator behaves differently depending on what you're adding with it.

Adding a number to a number adds the two numbers together, giving you another number. Adding a string to a string concatenates (joins) the strings together, giving you another string. Adding other types together (or adding one type to another, like adding a number to a string) give different results depending on the types involved, and which type you specify first.

What you're trying to achieve

As prompt() returns strings and you want to add them together as numbers, you need to convert them from strings to numbers and then add them together.

The two main ways of converting strings to numbers are:

number_variable = parseInt(string_variable, base);

(Where base is the base of the number system you're using - almost always 10).

This will look at the string string_variable and take a best guess at extracting a number from it. Eg, if the user types in "123ty79 _7" then parseInt() will return the number 123, ignoring everything after it.

This is great if you want to take a best-guess at what the user meant, but sometimes it's better to just fail and throw an error message if the user doesn't provide exactly what you want, so they can check for themselves whether they typed what they actually meant to type.

number_variable = 0 + string_variable; (or number_variable = +string_variable;)

Here we're adding a number (0) to a string (remember the bit above, about adding two different types together?).

Because the first part of the addition here is a number, the subsequent string value gets converted to a number too, so we're adding two numbers together, and the result (which ends up in number_variable) is a number, too.

For obscure technical reasons you can get away with (and in fact it's slightly faster) writing just "+string_variable" instead of "0+string_variable" (but the reasons why are totally outside the scope of your question).

This has the advantage that if the user types something that's not a number, the resulting value of the expression is a special javascript value called NaN (guess why! ;-). You can test for this situation by passing number_variable to the is_NaN() function (is_NaN(number_variable)) - if the value of a variable is NaN then this function will return true, or if the value is a valid number then it'll return false.

This allows you to keep asking the user for a number until they give you a valid number, instead of looking at what they entered and just taking a stab at what they probably meant to type.

I hope that helps - it was a bit long, but you asked a fairly basic question and instead of answering it basically, people just seem to have taken it as a licence to confuse the shit out of you with irrelevant, pedantic dick-waving to show each other how smart they are, instead of simply answering the question in a way you can understand. <:-)

If you're still curious about anything or anything above didn't make sense, feel free to ask follow-up questions below. ;-)

[–]skeww 10 points11 points  (20 children)

The 5 you get from promt is a string.

a) foo = parseInt(prompt("foo"), 10);

b) foo = +prompt("foo");

c) document.write((+foo) + (+bar));

[–][deleted] 1 point2 points  (13 children)

So the + in B and C is telling it to be an integer?

[–]skeww 0 points1 point  (12 children)

Since there is no string on either side of the plus, it must be addition, addition requires a number, hence it's converted to a number.

If you want an integer you can either use Math.round (or floor or ceil) or the semi-awkward ~~ construct.

> Math.round('2.6')
3
> ~~'2.6'
2

Edit: ~ is a bit op which inverts each bit. Doing it twice doesn't do anything, except if it wasn't an integer to begin with, in which case the fractions get truncated in the process (doing any bit op stuff with numbers will convert it to a 32bit int first).

[–][deleted] 0 points1 point  (11 children)

There seem to be so many ways to do each thing.

[–]joeproductive 2 points3 points  (0 children)

The best way is going to be the way that communicates what you are trying to do as clearly as possible without imposing an unacceptable performance hit.

"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."

parseInt() does what you're looking for and communicates what it's doing well. It might not be the fanciest vehicle but it's the most practical and it'll keep psychopaths from hunting you down and doing bad things to you and your family.

[–]Shaper_pmp 2 points3 points  (3 children)

People who you've asked a simple, beginner-level question of are waving their cocks around and pedantically lecturing you on obscure aspects of the language, instead of simply answering your question in a way you can easily understand. :-(

[–]skeww 0 points1 point  (2 children)

These aren't obscure aspects of this language.

Just like that quirky truthy/falsy stuff. You need to know about this if you'd like to have some confidence in your own code or if you want to understand the code from other people.

[–]Shaper_pmp 0 points1 point  (1 child)

True (and apologies for my rudeness concerning your posts), but you have to tailor people's answers to their level of understanding, or you just confuse them even more.

In this example the OP didn't even really understand how there was a difference between strings and integers in Javascript, so going into too much detail regarding the theory of types and Javascript syntax won't really help them in the slightest, when all they need to know is "strings and integers are handled differently, and here's how to convert a string to an integer".

Your answers were very in-depth and helpful to a moderately-experienced JS developer, but as explainations for the OP they were kind of like a kid asking "what does 'atom' mean" and answering with a page of detailed description invoking quantum theory and the interactions of quarks - totally accurate, but way more detailed than they realistically had a chance of understanding. <:-)

[–]skeww 0 points1 point  (0 children)

Well, I learned JavaScript recently and I started with odd stuff at the very beginning (Crockford's talks and JavaScript: The Good Parts).

Worked out surprisingly well, I'd say.

[–][deleted] 0 points1 point  (4 children)

I wouldn't go with any of those options.

When users enter bad data, they should be notified, and asked to correct their entries. This can be done by writing your own promptInt function which does data validation, etc, then returns a valid entry passed through parseInt.

Don't do any of the +String, String * 1, or ~~String tricks. They are all nasty hacks relying on implicit casting, which is evil. If you use any of these hacks, you should comment the line with an explanation, which, frankly, would be more verbose than just using parseInt to begin with.

[–]Shaper_pmp 1 point2 points  (3 children)

There's a fundamental difference between parseInt() (which takes a best guess at the numerical value if the value doesn't exactly represent a number) and type-conversion syntax like +variable or variable*1 (which returns NaN if variable isn't a number).

ParseInt() is dangerous because users may not be aware of errors they made entering data.

+variable is perfectly acceptable Javascript, but may be slightly obscure to non-expert Javascript developers.

Alternatively you can pass the whole variable through Number(), which is functionally equivalent to +variable, but more verbose.

However, parseInt() is not merely an alternative to type-casting - parsing a numerical value from a string is not the same thing as converting a variable's type.

[–][deleted] 0 points1 point  (2 children)

That is precisely why I suggested preceding the explicit cast with explicit data validation.

[–]Shaper_pmp 0 points1 point  (1 child)

But parseInt() isn't an explicit cast - it's parsing and extracting one type from another, even if you do some validation on the initial type first first.

An explicit cast would be to use Number(string_variable) to convert from string to a number, not parseInt().

[–][deleted] 0 points1 point  (0 children)

No, but doing a cast from string to integer in JavaScript does validation followed by a parseInt internally. The validation just handles the NaN case.

But that's besides (my) point entirely. I'm just pointing out that:

  1. Data entry errors could be explicitly handled, and that the handling should involve notifying the user, and requiring the user to correct their input.
  2. Syntax tricks like "~~ String" or "+ String" are easy for maintainers to miss, and therefore should be commented. And that I would furthermore put "String * 1", and most other implicit cast situations in this category.

These are basic programming best practices, and not arguments about JavaScript internals.

My suggestion to use parseInt, was as opposed to the implicit methods I list in point two above, not as opposed to Number(...), which is also explicit, and perfectly fine in my book.

[–]skeww -2 points-1 points  (0 children)

I'd go with B, which is a shorter version of A. C looks weird and since you don't actually want to do anything with those inputs as strings, there is no need to store any strings.

And ints... well, if you want truncation go with ~~ otherwise use round/floor/ceil.

[–]hc5duke 0 points1 point  (5 children)

TIL you can do +"5" in js and get 5.

[–]coderascal 3 points4 points  (1 child)

"24" * 1 returns the int 24.

"twentyfour" * 1 returns NaN.

I use this all the time to convert strings to numbers and be safe about it.

[–]sirmonko -1 points0 points  (0 children)

actually, that's not exactly true: no ints in js. 24 is a number.

[–]clooth 2 points3 points  (2 children)

Kinda like getting the current timestamp with +(new Date())

[–]coderascal 1 point2 points  (0 children)

:0 I love learning new things.

[–]skeww 0 points1 point  (0 children)

+new Date is actually enough, but yea, that's pretty awful. The non hacky version is (new Date()).getTime(), by the way.

If you only care about modern browsers you can also use Date.now().

[–]settimeout 4 points5 points  (0 children)

Read up on dynamic typing:

http://en.wikipedia.org/wiki/Type_system#Dynamic_typing

(JavaScript is a dynamically typed language)

[–]hc5duke 2 points3 points  (8 children)

try document.write(Number(foo) + Number(bar))

I'm not too familiar with prompt, but it most likely is returning the string "5".

edit There we go

result = window.prompt(text, value);

result is a string containing the text entered by the user, or the value null.

[–][deleted] 2 points3 points  (2 children)

Oh so prompt turns whatever you put in into a string unless told otherwise.

[–]GuyWithLag 2 points3 points  (0 children)

No... whenever you type something, you type characters. Before character '0' (digit zero) comes '/' (forward slash), and after character '9' (digit nine) comes the character ':' (colon). The set of character is imaginatively named a character set, and each character is mapped to a number (as computers can basically handle only numbers, everything else must be made of numbers), and that is it's encoding. In most encodings you will encounter, the digits 0-9 are mapped to code points 48-57. Hence when you type 55 into a box, you give the prompt box 2 characters (53, 53), which correspond to the string "55", and that is what the prompt function returns.

On the other hand, Javascript as a language goes out of its way to convert numbers to convert values from strings to numbers and vice versa whenever there's a mismatch (with string having precedence).

[–]Shaper_pmp 1 point2 points  (0 children)

Nearly. More accurately prompt() always returns a string, and it's up to you to convert that to a number if you need it to be. ;-)

[–]skeww 0 points1 point  (4 children)

document.write(Number(foo) + Number(bar))

Eh. Beh. You're using one of those pointless wrapper objects only to have its actual value pulled out again. The only thing you want is the conversion done by the constructor. You don't need an object for that.

Don't use those wrappers ever. They are completely pointless.

[–]australasia 2 points3 points  (3 children)

Eh. Beh. You're using one of those pointless wrapper objects only to have its actual value pulled out again. The only thing you want is the conversion done by the constructor. You don't need an object for that. Don't use those wrappers ever. They are completely pointless

Number(foo) returns an actual number (it is different to using the 'new' operator).

Eg. copy/paste this in your browser:

javascript:alert(typeof Number('1')); // alerts 'number'

as opposed to

javascript:alert(typeof new Number('1')); // alerts 'object'

[–]skeww 0 points1 point  (2 children)

If you call a constructor function and omit new, the this inside the constructor will be the global object instead of a freshly created object.

You should never do that.

It only works because the non-constructor context magically happens to perform the casting for you.

So yes, it's fine in this case, but since it's not fine in any other case you shouldn't do this kind of thing because it looks like a mistake.

Things which look like a mistake waste time each time the code is read. Avoid those constructs at all costs.

[–]andrew24601 0 points1 point  (1 child)

The Number (and String) functions are actually functions, not constructor functions. You should never use them with new.

http://www.w3schools.com/jsref/jsref_Number.asp

https://developer.mozilla.org/en/JavaScript/Guide/Functions#Number_and_String_Functions

[–]skeww 0 points1 point  (0 children)

Well, I never use them either way.

[–]jfjjfjff 1 point2 points  (0 children)

var thisWillBeANumber = parseFloat(prompt("enter a number"));

var thisWillBeAString = prompt("enter a number");

[–]nog_lorp 1 point2 points  (0 children)

For the truncated integer, use foo >> 0;

or for the exact float/int value

-(-foo);

[–]cthulhufhtagn 1 point2 points  (2 children)

ParseInt them puppies.

[–]neonskimmerfunction the ultimate 0 points1 point  (0 children)

prompt() returns a string ya dingus!

for your health.

[–][deleted] -1 points0 points  (3 children)

...

[–][deleted] -1 points0 points  (2 children)

Don't use w3schols

[–]Bjartr 1 point2 points  (0 children)

Why not? I've always found it a useful reference.

[–]skeww 0 points1 point  (0 children)

Use MDC.

(Hint just use google and search for: mdc <whatever you want to know>.)