max-mapper / art-of-node

:snowflake: a short introduction to node.js
https://github.com/maxogden/art-of-node#the-art-of-node
Other
9.79k stars 856 forks source link

parseInt mystery #47

Closed mgruesbeck closed 9 years ago

mgruesbeck commented 9 years ago

This isn't so much an issue as I'm just hoping to discuss an example and learn more spells. Hope that is ok here!

I was fiddling with the code example below when I noticed you don't need to call parseInt in order for the ++ operand to work on myNumber. I modified the example with setTimeout to verify this.

As a test I also tried to pass fileContents into console.log(typeof()) from within the addOne function. I expected this would return string but instead it returned object.

My question is twofold. First, why will this example work without parseInt? Second, why does typeof(fileContents); return object instead of string. I'll appreciate any input. Thanks!

var fs = require('fs');
var myNumber = undefined;

function addOne() {
  fs.readFile('number.txt', function doneReading(err, fileContents) {
    /// console.log(typeof(fileContents)); logs an object
    myNumber = parseInt(fileContents);
    /// myNumber = (fileContents); works without parseInt
    myNumber++;
  })
}

addOne();

setTimeout(function() {
    console.log(myNumber); /// logs myNumber++
}, 1000);
maxbeatty commented 9 years ago

why does typeof(fileContents); return object instead of string

If no encoding is specified for readFile, then the raw buffer is returned which is why typeof is reporting an object. The Buffer class provides a method to inspect an object to see if it is a buffer (isBuffer).

Buffer.isBuffer(fileContents) // should return true

To make fileContents a string, you can either provide an encoding option for readFile or call toString on fileContents.

why will this example work without parseInt?

parseInt converts its string param to a string if it isn't one already (effectively fileContents.toString()). Increment (++) doesn't document as such, but with a little testing I saw it behave the same as you could expect a string when performing arithmetic.

var assert = require('assert');

function increment(n) {
  nn = n++
  // increment returns s as a number to nn
  assert.equal(typeof(nn), 'number')
  // n is now also a number (not original type) and has value incremented
  assert.equal(typeof(n), 'number')
  assert.equal(n, 2)
}

// strings as numbers
s = '1'
assert.equal(typeof(s), 'string')
increment(s)

// buffers as numbers
b = new Buffer('1')
assert(Buffer.isBuffer(b))
increment(b)

Mystery solved?

mgruesbeck commented 9 years ago

Awesome @maxbeatty!! It's a mystery no more.

You also gave me some neat tests to play with as well! Thanks for that. A great experiment for the making of new spells and potions.

Cheers!