Monday, 22 August, 2016 UTC


Summary

Every developer that has worked with JavaScript knows the frustration of “undefined is not a function”.
Most of the time the cause is something simple, though.
A quick survey of StackOverflow questions around this error message shows some basic examples, such as:
  • Mis-spelled function name
  • Capitalization of words in function name
  • jQuery is in “no-conflict” mode and “$” doesn’t exist
  • Calling methods that don’t exist
  • And more
The questions around this often come down to simple mistakes made during the development process.
It’s easy to misspell a word or get capitalization wrong, for example. And sometimes we get the <script> tags in the wrong order, or forget to include a script tag entirely.
Fortunately, most of these simple problems have simple solutions.
In the case of spelling mistakes and capitalization problems, you correct the mistake and move on.
When you run into jQuery in “no conflict” mode, you just replace your $() function calls with jQuery() and life is good.
This error does become significantly more frustrating, though.
When you start getting into more obscure problems – the ones that are not necessarily your fault – it’s easy to go from annoyed by a simple mistake to angry at a problem that is plaguing you.
Like a 3rd party library removing a function.
Tiago Garcia relates a story, via Twitter, as an illustration of this error, and a potential downside of relying on other people’s code.
@derickbailey we had a 3rd party lib being injected on the page which had this function, its name got changed, so we were getting that error
— Tiago Garcia (@tiagooo_romero) August 11, 2016
That’s not to say all 3rd party code is bad or dangerous. But, there are times when we can see common errors caused by uncommon problems.
In Tiago’s case, he had to put in a check to ensure the function was available when the script loaded.
That took a little more code, but was still a fairly simple solution.
There are tools that can help. Sometimes.
Linting tools like JSHint and ESLint can show you variable and function names that are not defined, for example.
These tools won’t catch every problem, though.
Linting tools typically don’t know what methods exist on objects, for example. You would need runtime analysis of the code for that to be accurate, as objects are often composed at runtime.
Worse than objects and methods, though, are the errors that only occur at runtime because of the way JavaScript’s “this” keyword can change.
Seeing a message like “this.doSomething is not a function” can be infuriating when you look at the code in question and see the method right there, on the object.
You know the method is there. You can see it with your own eyes!
But the JavaScript runtime says it’s not there, at runtime.
This is a case where the simple rules and reasons that are typically associated “undefined is not a problem” break down and fail.
It isn’t a simple misspelling or capitalization problem. It’s not a function that disappeared without warning, either.
It’s a case of runtime definitions changing – differing from what was intended at the time of writing code the code.
JavaScript’s “this” strikes again.
And “this” is perhaps the most notorious keyword in any language.
Not because of strange or unique behavior, but because of the deceptively familiar behavior in many situation.
It’s easy to see code like “this.doAmazingThings()” and assume “this” references the object on which the method was defined. This is how other languages, like C#, work. So why would JavaScript be any different?
The truth, however, is that JavaScript manages “this” at runtime, and can change the value of “this” for any of several different reasons.
In the above example, for instance, jQuery may be calling this method from an event, setting “this” to the element that produced the event.
You could use the classic “var that = this” technique to fix “this”.
Most developers – myself included – have written code like this hundreds, if not thousands of times.
By taking advantage of a JavaScript closure around “that”, the callback function can work as expected.
While this technique does solve the immediate problem – and I do have a long history of writing code like this – I rarely use this trick anymore.
Instead of ignoring the underlying rules for managing “this” in JavaScript, as this technique would have you do, take the time to learn the rules.
They aren’t too numerous, or difficult.
The core of JavaScript’s “this” comes down to a single principle, in fact.
And I’ll share that principle with you in my Mastering JavaScript’s “this” email course.
Sign up for the free 7 day email course, below.
I’ll send you the secrets to one of JavaScript’s most misunderstood fundamentals.
Tweet