I'm fairly new to JavaScript and Backbone and I came across this error.
Router = Backbone.Router.extend({
routes: {
":albumID": "load"
},
load: function (albumID) {
if (controller.collectionInitialized == true) {
console.log("RESET");
album.trigger("clear");
}
var album = new Album([], {
title: albumID
});
controller.trigger("collectionInit");
controller.trigger("switchAlbum", albumID);
}
});
Controller = Backbone.Model.extend({
currentAlbum: "",
collectionInitialized: false,
initialize: function () {
console.log("controller is initialized");
this.on("switchAlbum", function (newAlbum) {
this.currentAlbum = newAlbum;
});
this.on("collectionInit", function () {
this.collectionInitialized = true;
});
}
});
Album = Backbone.Collection.extend({
initialize: function (models, options) {
this.on("clear", this.clear);
},
clear: function () {
this.reset();
this.off();
}
});
I get this error: Unable to get property 'trigger' of undefined or null reference
. The if
statement makes sure that album
already exists before triggering clear
. Previously I tried just calling album.reset()
directly but got the same error. My guess is that it's some kind of scoping problem, could someone please point me in the right direction?
It's true that in Javascript variables are function-scoped
, meaning they're visible all over their local scope (ie the function host), but instantiation is a different beast.
load: function (albumID) {
if (controller.collectionInitialized == true) {
console.log("RESET");
album.trigger("clear");
}
var album = new Album([], {
title: albumID
});
controller.trigger("collectionInit");
controller.trigger("switchAlbum", albumID);
}
You create a new Album
after you call method trigger
on album, thus resulting in a null reference.
Also, even if you call the function twice (ie the first time having controller.collectionInitialized
as false
, and the second time as true
), since the variable album
is local to the function it's always undefined when you enter the if
body, because its scope is the function load
, so it " dies " every time the end of load
's body is reached.
Amith George provides the correct solution to your problem: define the variable album
at one scope level higher (ie the level of the object you pass as argument to the extend
method)
EDIT
Re-reading the code, assuming controller
is a valid instance and exists, and assuming that the controller.collectionInitialized
is set to true, you are basically calling a method trigger
on a variable album
whose value is null.
Using JS hoisting rules, your load function could have be written as
load: function(albumID) {
var album = null;
if (controller.collectionInitialized == true) {
console.log("RESET");
album.trigger("clear");
}
album = new Album([], { title: albumID });
controller.trigger("collectionInit");
controller.trigger("switchAlbum", albumID);
}
Maybe, the above re-writing makes it clear that even if controller.collectionInitialized
is true
, album
is a local variable and is always reset to null each time the load function is called.
What ever mechanism you used to enable global access to controller
, use the same means to enable global access to album
. Do not re-declare album
as local to the function.
...
It may help to read more about Javascript variable and function hoisting .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.