Mastering Javascript Fundamentals: AccountingJS Internal Helper Methods (Part 1)
Get the fundamentals down and the level of everything you do will rise. - Michael Jordan
As stated in my original post, I do 1 hour of video lessons from Watch and Code every day. If you're interested in learning Javascript in a way that goes beyond basic tutorials and gives you a foundational, practical knowledge without relying on frameworks - I'd highly recommend it. If you're reading these posts, please keep in mind that these are just my notes, and I'm not an expert (yet!). If your goal is also to master the fundamentals of Javascript, please head over to Watch and Code and start your journey there!
All screenshots were annotated using Shotty.
AccountingJS Internal Helper Methods
Continuing on with the rest of the helper methods in AccountingJS, next we have a helper method called isArray. Notice that the comments say that it "delegates to ECMA5's Array.isArray".
isArray
This means that if you're using ES5 or later, AccountingJS will just use the built in Array.isArray method, and if you're using an older browser, it will use its own similar version.
Let's see how it works in the console.
All you do is pass in something and it tells you whether or not it's an array.
Inside of AccountingJS, it saves a reference to this built in Array.isArray function in a variable called nativeIsArray:
In the unlikely case that you're using a very old browser that doesn't have Array.isArray, Array.isArray will be undefined, and the AccountingJS isArray method will have a fallback for that case.
This fallback case in AccountingJS is a little unusual. The fallback cased uses toString, and it may not be obvious why it would use toString while dealing with arrays.
Arrays have their own toString method on their prototype. This toString method shows you what's in the array (as a string, obviously):
So Array.prototype.toString is useful in showing you what's in the array, but not useful in showing you what data type it is.
In contrast to Array.prototype.toString, Object.prototype.toString actually is helpful in giving us information about data types.
We want to use Object.prototype.toString to tell us whether something is an array or not.
Let's say we have an empty object:
And then we do:
Since myObject is an object, it's going to have access to Object.prototype methods like toString.
So,
will actually call:
The key thing to point out here is that, when you call .toString() as a method, the this keyword will be equal to whatever is to the left of the dot. In our case, that's myObject:
So if you wanted to use toString() on something else, all you'd have to do is change this to another value.
Luckily we have a mechanism to do that in Javascript, we can use the call() method on objects.
So if you do:
It allows you to call toString, and also set this to whatever you choose.
So we can set this to an empty array, and it will give us information about that array:
So we're essentially borrowing a method from objects, and we're using it on our array instead. We're manipulating the this value inside of toString to achieve this effect.
This is the strategy that AccountingJS uses.
We can see there are shortcuts to Array.isArray and Object.prototype.toString (because we're going to use them inside of our isArray function.
There's only one line inside of isArray, but it's pretty dense. We have a ternary operator (?) that says if nativeIsArray exists, then it will just return nativeIsArray and pass in the object.
Remember, if nativeIsArray exists, it will be equal to Array.isArray:
Array.isArray just returns true or false, depending on whether the object passed in is an array or not.
Now in the fallback scenario: if nativeIsArray does not exist, then the ternary operator will move to this side:
This is where it uses the call() trick that we just looked at.
Remember that toString is a shortcut to Object.prototype.toString:
So our code uses .call() to call toString(), with the this value set to obj:
So it will turn obj (which can be whatever you want) into a string. Only if obj is an array will it return this value of '[object Array]'
If that comparison is true, then the whole isArray function will return true.
That's how the isArray function works.
isObject
The next function, isObject, is pretty similar to isArray.
The function will only return true if both of these things are true:
The first one is: if the corresponding boolean value for obj is true, it will move to the second part of the "and" statement.
Then it will check to see if toString.call(obj) returns '[object Object]'.
That will only happen if obj is a plain (or "true" as AccountingJS calls it) object.
We can see this in action in the console:
Summary:
isArray
- Tells you whether something is an array or not.
- Uses the native isArray if browser supports ES5 or later.
- Uses hand-rolled implementation if not.
.call()
- a nice trick to borrow a method from one object and call it on another.
- when you use .call(object) you set the this value to object for whatever is to the left of the dot.
- AccountingJS uses Object.prototype.toString(obj) to show us the type of obj (and uses an equality check).
isObject
- Uses same techniques as isArray, but instead checks to see if something is a plain object (not an array, string, number, etc.).