Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Uncaught TypeError: undefined is not a function" - Beginner Backbone.js Application

I'm setting up a pretty simple app with backbone, and I'm getting an error.

Uncaught TypeError: undefined is not a function example_app.js:7 ExampleApp.initialize example_app.js:7 (anonymous function) 

This is where the error is showing up in Chrome Inspector (init file - example_app.js):

var ExampleApp = {   Models: {},   Collections: {},   Views: {},   Routers: {},   initialize: function() {     var tasks = new ExampleApp.Collections.Tasks(data.tasks);     new ExampleApp.Routers.Tasks({ tasks: tasks });     Backbone.history.start();   } }; 

Here's my tasks index.haml file

- content_for :javascript do   - javascript_tag do     ExampleApp.initialize({ tasks: #{raw @tasks.to_json} });  = yield :javascript 

models / task.js

var Task = Backbone.Model.extend({}); 

collections / tasks.js

var Tasks = Backbone.Collection.extend({     model: Task,     url: '/tasks' }); 

routers / tasks.js

ExampleApp.Routers.Tasks = Backbone.Router.extend({     routes: {         "": "index"     },      index: function() {         alert('test');         // var view = new ExampleApp.Views.TaskIndex({ collection: ExampleApp.tasks });         // $('body').html(view.render().$el);     } }); 

And here's proof that I'm calling all of the files (I think):

<script src="/assets/jquery.js?body=1" type="text/javascript"></script> <script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script> <script src="/assets/jquery-ui.js?body=1" type="text/javascript"></script> <script src="/assets/underscore.js?body=1" type="text/javascript"></script> <script src="/assets/backbone.js?body=1" type="text/javascript"></script> <script src="/assets/backbone-support/support.js?body=1" type="text/javascript"></script> <script src="/assets/backbone-support/composite_view.js?body=1" type="text/javascript"></script> <script src="/assets/backbone-support/swapping_router.js?body=1" type="text/javascript"></script> <script src="/assets/backbone-support.js?body=1" type="text/javascript"></script> <script src="/assets/example_app.js?body=1" type="text/javascript"></script> <script src="/assets/easing.js?body=1" type="text/javascript"></script> <script src="/assets/modernizr.js?body=1" type="text/javascript"></script> <script src="/assets/models/task.js?body=1" type="text/javascript"></script> <script src="/assets/collections/tasks.js?body=1" type="text/javascript"></script> <script src="/assets/views/task_view.js?body=1" type="text/javascript"></script> <script src="/assets/views/tasks.js?body=1" type="text/javascript"></script> <script src="/assets/views/tasks_index.js?body=1" type="text/javascript"></script> <script src="/assets/routers/tasks.js?body=1" type="text/javascript"></script> <script src="/assets/tasks/index.js?body=1" type="text/javascript"></script> <script src="/assets/tasks/task.js?body=1" type="text/javascript"></script> <script src="/assets/application.js?body=1" type="text/javascript"></script> 

Any ideas would be great. Thanks!

like image 678
jake Avatar asked Nov 21 '12 22:11

jake


1 Answers

Uncaught TypeError: undefined is not a function example_app.js:7

This error message tells the whole story. On this line, you are trying to execute a function. However, whatever is being executed is not a function! Instead, it's undefined.

So what's on example_app.js line 7? Looks like this:

var tasks = new ExampleApp.Collections.Tasks(data.tasks); 

There is only one function being run on that line. We found the problem! ExampleApp.Collections.Tasks is undefined.

So lets look at where that is declared:

var Tasks = Backbone.Collection.extend({     model: Task,     url: '/tasks' }); 

If that's all the code for this collection, then the root cause is right here. You assign the constructor to global variable, called Tasks. But you never add it to the ExampleApp.Collections object, a place you later expect it to be.

Change that to this, and I bet you'd be good.

ExampleApp.Collections.Tasks = Backbone.Collection.extend({     model: Task,     url: '/tasks' }); 

See how important the proper names and line numbers are in figuring this out? Never ever regard errors as binary (it works or it doesn't). Instead read the error, in most cases the error message itself gives you the critical clues you need to trace through to find the real issue.


In Javascript, when you execute a function, it's evaluated like:

expression.that('returns').aFunctionObject(); // js execute -> expression.that('returns').aFunctionObject // what the JS engine does 

That expression can be complex. So when you see undefined is not a function it means that expression did not return a function object. So you have to figure out why what you are trying to execute isn't a function.

And in this case, it was because you didn't put something where you thought you did.

like image 112
Alex Wayne Avatar answered Oct 06 '22 03:10

Alex Wayne