14

I'm using backbone.js along with jquery and underscore.js

Here's some of my code (it doesn't do anything yet). The strange thing is that upon hitting the url "/#users" there isn't an error. The only time the error happens is when I then click to go to a different hash and then click back to go to "/#users". Here's part of my code, with the line that receives the error toward the end Users = new Users(); the error says "Users is not a constructor":

var User = Backbone.Model.extend({
    url: function(){return 'api/user/id/' + this.id;}
});

var Users = Backbone.Collection.extend({
    model: User,
    url: function(){return 'api/users';},
    initialize: function() {
    }
});

var UsersView = Backbone.View.extend({
    initialize: function() {
        this.users = this.options.users;
        this.render();
    },

    render: function() {
        _(this.users).each(function(){
        //  $('#app').append('here');
        });

        var template = _.template($('#usersTemplate').text());

        $(this.el).html(template({users: this.users}));
        $('#app').html(this.el);
    }
});

var UserView = Backbone.View.extend({
    initialize: function() {
        this.user = this.options.user;
        this.render();
    },

    render: function() {

        var template = _.template("hello {{user.name}}");

        $(this.el).html(template({user: this.user.toJSON()}));
        $('#app').html(this.el);
    }
});

var Controller = Backbone.Controller.extend({
    routes: {
        'dashboard' : 'dashboard',
        'users' : 'showusers'
    },

    showuser: function(id) {
        UserList.fetch({
            success: function(){
                new UserView({user: User});
            },
            error: function(){
                alert('an error of sorts');
            }
        });
    },

    showusers: function() {
        Users = new Users();
        Users.fetch({
            success: function(Users) {
                new UsersView({users: Users});
            },
            error: function() {
            }
        });
    },

    dashboard: function() {
        Users = new Users;
        Users.fetch({
            success: function() {
                new UsersView({users: Users});
            },
            error: function() {
            }
        });
    }
});

$(document).ready(function(){
    var ApplicationController = new Controller;
    Backbone.history.start();
});

the accompanying html if you're curious:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Administration Panel</title>

    <!-- Framework -->
    <script src="/javascripts/jquery.min.js"></script>
    <script src="/javascripts/underscore.min.js"></script>
    <script src="/javascripts/backbone.js"></script>

    <!-- Application -->
    <script src="/javascripts/application.js"></script>

    <script id="usersTemplate" type="text/x-underscore-template">
        asdf
    </script>

</head>
<body>

<div>
<a href="#dashboard">Dashboard</a>
<a href="#users">Users</a>
<a href="#products">Products</a>
<a href="#orders">Orders</a>
<a href="#pages">Pages</a>
<a href="#settings">Settings</a>
</div>

<div id="app"></div>

</body>
</html>

2 Answers 2

25

new can only be used with a Function as the operand.

new {}  // Error: ({}) is not a constructor

Check the type of Users in context: it is not a Function when that exception is raised.

Happy coding


alert(typeof(Users)) ought to do the trick. The result should be "function" to be usable as a constructor. Take note of what it is in the failing case, and see below for a reason.

One problematic scenario (for Users = new Users) may be: an object is constructed from the Function Users and then the object (now not a Function/constructor) is assigned back to Users so the next new Users will go kaboom! (Look in both showusers and dashboard -- is that behavior really intended?)

The 'correct' code is likely: var users = new Users; users.blahblah(...); that is, use a new local variable and do not overwrite the global Users variable/property.


The reason the error is only generated when "going back" to "#foobar" (a Fragment Identifier) is that no new page is actually loaded and thus the JavaScript is not reloaded and the current (now corrupt Users) is being used. kaboom!

Excerpt from Fragment Identifier:

If the targeted element is located in the current document, a user agent may simply focus the targeted element without having to reload it ...

Sign up to request clarification or add additional context in comments.

3 Comments

I ran into this error when naming a model "history" only in FF while working in Chrome, possibly due to another library I was loading.
@steve76 Yes, any name clashes can result in icky behavior. In the case of history I suspect it clashing with window.history. In Firefox setting a "built-in" window property does not report an error but also does not change the value: and window.history is not a function/constructor.
One caveat, you can't use labda functions as constructors: new (() => {}) // (intermediate value) is not a constructor
0

I think its Syntax Error

this happened with me when I tried to return anonymous object in my function

 var FalsEextension=false;
 ........
 ........
 return new  { FalsEextension, LargeFile };// wrong Syntax 

and the correct Syntax is

 return { FalsEextension, LargeFile };

and you can use it like this

ObjectName.FalsEextension

1 Comment

Your example is already covered by the accepted answer. it fails for the same reason new {} fails.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.