It's actually due to this acting...weirdly in Javascript compared to most other languages you may have used.

In your first example, you call $http.get(). Because of how this works in JS, the get() function will be called, with this being set to whatever this.$http is in this case. This is where the funky-ness starts though. this is only set when you call a method on an object, and remains the same when a new function is called. This means that when $http.get() calls your callback, this is still set to $http and thus $state doesn't exist.

This is why you see the pattern of var self = this; all over the place. It allows you to have a binding to this that you know about, so the following would work:

Lambda functions, on the other hand, bind differently. So called "arrow functions" don't have their own this context, and thus close over the this in the function in which they were created, so they work as you expect.