1

我对 JavaScript 和 Backbone 还很陌生,我遇到了这个错误。

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();
    }

});

我得到这个错误:Unable to get property 'trigger' of undefined or null reference。该if语句确保album在触发之前已经存在clear。以前我尝试直接调用album.reset()但得到了同样的错误。我的猜测是这是某种范围界定问题,有人可以指出我正确的方向吗?

4

2 回答 2

1

编辑

重新阅读代码,假设controller是一个有效的实例并且存在,并假设controller.collectionInitialized设置为true,你基本上是在一个值为nulltrigger的变量上调用一个方法。album

使用 JS 提升规则,你的加载函数可以写成

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);
}

也许,上面的重写清楚地表明,即使controller.collectionInitializedis truealbum也是一个局部变量,并且每次调用 load 函数时总是重置为 null 。

无论您使用什么机制来启用全局访问controller,都使用相同的方式来启用全局访问album。不要重新声明album为函数的本地。

...

阅读有关Javascript 变量和函数提升的更多信息可能会有所帮助。

于 2013-05-08T17:54:05.470 回答
1

确实,在 Javascript 中变量是function-scoped,这意味着它们在其本地范围内(即函数宿主)都是可见的,但实例化是另一种野兽。

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);
}   

您在专辑上调用方法new Album 创建一个trigger,从而导致空引用。

此外,即使您两次调用该函数(即第一次具有controller.collectionInitializedas false,第二次具有 as true),由于该变量album是函数的本地变量,当您进入if主体时它始终是未定义的,因为它的范围是函数load,所以它每次到达 's 身体的尽头时都会“死亡”。load

Amit George为您的问题提供了正确的解决方案:album在更高的范围级别定义变量(即您作为参数传递给extend方法的对象级别)

于 2013-05-08T16:31:46.097 回答