Undefined

is not a

Function

or what the most common errors

in JavaScript really mean

by Max Beizer / @maxbeizer

$ whoami

  • developer at Centresource
  • NSS Cohort One graduate
  • Nashville stereotype (in recovery)
  • @maxbeizer everywhere

Credit

Where Credit

Is Due

Object-Oriented JavaScript

by Newton Saber

David Calhoun

Andy Matthews

Jason Orendorff

Morgan (Reece) Phillips

Eliza Brock

Your

Nodevember

Organizers

all my mentors

whose names have been omitted

to protect the innocent

Why Am I Here?

What is

the single most

common error

JS developers

make?

Writing

JavaScript

Writing Javascript …

with wanton disregard

for understanding

how Javascript works

Guilty

Javascript

is a pillar

of the web

Javascript

is the herpes

of the web

There Is

No Known Cure

It's Spreading

A Peek

Under

the Covers

Better Understanding

Happier

and

Faster

Development

Who Will Get

The Most Out

Of This Talk?

The JS Beginner

X < JS Master

Anyone Who

Is Used To

Seeing Red

In The Console

Who Will Get

Nothing Out

Of This Talk?

The Blissfully Ignorant

The C/C++ Expert

The Faint of Heart

What We

Will Cover?

Why

Types Matter

to JS devs

What this Means

in a specific sense

Objects

a view from

(closer to)

the metal

What We

Will Not Cover

Hello World Syntax

DOM Traversal

AJAX / Promises

If You Leave With

Nothing Else

Objects Hold

References

To Primitives

(Or Other Objects)

Our Story

Begins With

Memory

Do not be afraid

each slot represents a slice of memory with a unique address like 0x9FFF0

Primitives

Boolean

Floating Point Num

String

Symbol

(in ES6)

Special Cases

Value Properties

Global properties returning a simple value

null

undefined

NaN

Infinity

References

Object

Functions are

First-Class

Objects

Arrays are

Just Objects

Cool Story, Bro

Types


              var x;
            
My name is x and … ?

No Type Info


              int x;
            

A Dash of C

JavaScript

Is Not

Type-Safe

Awesome

Except

When it

Isn't

WAT

by Gary Bernhardt

Our Dear Friend:

+


              (num|string) + (num|string); // awesome sauce (maybe)
            

Add Other Types

Hilarity Ensues


              [] + []; // ???
              [] + {}; // ???
            

              [] + []; // ""
              [] + {}; // "[object Object]"
            

If input is primitive:

return it as is

Otherwise,

input is an object:

Call obj.valueOf()

If that result

is a primitive:

return it

Otherwise

call obj.toString()

If the result

is a primitive:

return it

Otherwise:

throw a TypeError

citation:

Dr. Axel Rauschmayer


              [] + []; ""
              [] + {}; "[object Object]"
            

              var array = [];
              array.valueOf() === array; // true, same for object
            

              toString([]); // ""
              toString({}); // "[object Object]"
            

It Actually

Gets Weirder

From Here

Where It Has

Stung Me


              var myWeight = '190'; // were only wishing made that so
              myNum + 50; // more like it
            

+

Adds

Numbers

+

Concats

Strings

Implicit

String

Conversion

Casting

or

Coercion

"19050"

:sad_trombone:

Or This


              if(peaceTreaty === 'undefined') {
                launchZeeMissiles();
              }
            

Actually Reads

Pretty Cleanly

Hold Onto

Your Butts

We're All

Gonna Die


              if(typeof peaceTreaty === 'undefined') {
                launchZeeMissiles();
              }
            

typeof

Distinguish

Primitives

From Each Other

And Objects

Remember

NaN ?


              NaN === NaN; // ???
            

              NaN === NaN; // false
            

Because

Of Course


               isNaN(NaN); // true
               var mySoCalledNum = Number("90s ftw"); // returns NaN
               // but not itself NaN
               isNaN(mySoCalledNum); // true -> implicit conversion
            

How About …


              var myBool = 'false';
              myBool === true; // ???
              myBool === false; // ???
            

              var myBool = 'false';
              myBool === true; // false
              myBool === false; // false
            

              var myBool = 'false';
              if(myBool === false) { // typeof myBool === 'string'
                partyInTheUSA();
              } else {
                theEndIsNigh = true;
              }
            

In Complex

Sytems

Conversions

Can Happen

Unexpectedly

Types

Matter

More

This

misunderstood

What You Need

To Know About

this

Reference to

a Given

Context


              var obj = {
                doAllTheThings: function() {
                  console.log(this);
                }
              };
              obj.doAllTheThings() === obj; // ???
            
I am an object My name is 'obj' My prototype is Object I have one method ^^ is located at some_hex_value my return address is …

Over at

some_hex_value

I am a function My name is 'doAllTheThings' My prototype is … I take zero arguments `this` is the memory address of obj my return address is …

              var obj = {
                doAllTheThings: function() {
                  console.log(this);
                }
              };
              obj.doAllTheThings() === obj; // true
            

Seems Reasonable

A Little

Too Reasonable


              function funkyFunc() {
                console.log(this);
              }
              funkyFunc(); // ???

              function somewhatFunkyFunc() {
                'use strict';
                console.log(this);
              }
              somewhatFunkyFunc(); // ???
            

Runtime Context

No Reference

i.e. unbound

Sloppy Mode

or

Quirks Mode


              function funkyFunc() {
                console.log(this);
              }
              funkyFunc(); // window
            

Strict Mode


              function somewhatFunkyFunc() {
                'use strict';
                console.log(this);
              }
              somewhatFunkyFunc(); // undefined
            
funkFunc this? window, I guess somewhatFunkyFunc this? undefined

Constructors


              var thisHuh;
              function MyObject() {
                thisHuh = this;
              }

              var instance = new MyObject();
              console.log(thisHuh === instance); // ???
            

New

(simplified)


              function newOperator(Constr, arrayWithArgs) {
                var thisValue = Object.create(Constr.prototype);
                Constr.apply(thisValue, arrayWithArgs);
                return thisValue;
              }
            
h/t Dr. Axel Rauschmayer, again
new Constr this is ^^^ arrayWithArgs

this

is a reference

To the Errors

Undefined is not

a Function


              var lloydChristmas = {};

              lloydChristmas.harryDunne(); // undefined is not a function
            
lloydChristmas is an object zero properties zero methods

no reference to harryDunne

harryDunne

Points to

undefined

undefined

a pseudo primitive

Not

Writable

Enumerable

or

Configurable

No Functions

No Properties


              var underfunded;
              underfunded.manDate;
              // TypeError: Cannot read property 'manDate' of undefined
            
undefined the value variables without values point ^^^ null is pretty similar undefined is also a global variable

If You Are

Doing This


              undefined = 'anything';
            

You Are

Doing It

Wrong

Objects

Objects … have properties house methods hold references can vary in memory footprint (i.e. Array.prototype.push() )

A Stack Frame

Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame Stack Frame

Stack Level Too Deep

Stack Overflow

Drilling Deeper

Consider Please

the Following


              var smarm = {
                aString: 'theory',
                aNum: 42,
                aBool: true,
                doFunc: function () {
                  var a = 'bob';
                  console.log(this); // smarm
                  (function () {
                    console.log(this); // window - 'this' is reset
                    console.log(a); // 'bob' - still in scope
                  }());
                }
              };
              smarm.doFunc();
            
Your Object: smarm at abc123 String at 123 Num at 456 Bool at 789 Object at 000

wide-angle

123 String: 'theory' 456 Num: 42.0 789 Bool: true 000 Object: doFunc smarm (this) is at abc123

A bit closer in

All reference smarm


              var smarm = {
                aString: 'theory',
                aNum: 42,
                aBool: true,
                doFunc: function () {
                  var a = 'bob';
                  console.log(this); // smarm
                  (function () {
                    console.log(this); // window - 'this' is reset
                    console.log(a); // 'bob' - still in scope
                  }());
                }
              };
              smarm.doFunc();
            
Object doFunc String at eee Object at fff smarm is at abc123

Even Closer

Still referencing smarm


              var smarm = {
                aString: 'theory',
                aNum: 42,
                aBool: true,
                doFunc: function () {
                  var a = 'bob';
                  console.log(this); // smarm
                  (function () {
                    console.log(this); // window - 'this' is reset
                    console.log(a); // 'bob' - still in scope
                  }());
                }
              };
              smarm.doFunc();
            
Anon. function at fff return address doFunc 000 this? this was reset

Elbow-Deep

No reference to smarm

Complete Lack

of smarm

Without

Reference,

We Know Where

this Goes

A Quick Word

On Prototypes

Consider


              var Developer = function() {
                this.back = 'bad';
                this.posture = 'worse';
                this.drinkCoffee = function() {
                  alert('I am on top of the world');
                };
              };
            
new Developer String: back String: posture Object: drinkCoffee

Repetition of

Function

Definition

Everytime

ETOOMUCHOBJECTSSTUFFS


              var Developer = function() {
                this.back = 'bad';
                this.posture = 'worse';
              };

              Developer.prototype.drinkCoffee = function() {
                alert('I believe I can fly');
              };
            
new Developer String: back String: posture Developer.prototype drinkCoffee is at some_hex

Function

Defined

Once

in the

Prototype

Prototypical

Inheritance

References to

Related Objects

It's All

Just Memory

It's All

Gray and White

Lines

In Summation

Javascript is Great

For Some Things

High-Level

(too)

Many Libraries

The First

Programming

Language

For Many

Many

(me, for example)

Write it Poorly

You Don't Have

to be a C++

Expert

Fundamental Concepts

Debug Faster

Develop Faster

Develop Better


              typeof happiness !== 'undefined'
            

Thank You

Questions?