调用回调时无法访问对象属性

时间:2014-05-05 13:34:34

标签: javascript oop

function Push(apiInstance) {
    this.api = apiInstance; // If I alert() here this is a valid object
    this.pushNotification = window.plugins.pushNotification;

    if ( device.platform == 'android' || device.platform == 'Android' )
    {
        this.pushNotification.register(
            this.successHandler,
            this.errorHandler, {
                "senderID":"",
                "ecb":"onNotificationGCM"
            });
    }
    else
    {
        this.pushNotification.register(
            this.tokenHandler,
            this.errorHandler, {
                "badge":"true",
                "sound":"true",
                "alert":"true",
                "ecb":"onNotificationAPN"
            });
    }
}

Push.prototype.tokenHandler = function (token) {
    this.api.registerDevice(token); // Suddenly this.api is undefined
};

var push = new Push(/* in my production code this is a valid object */);

我知道apiInstance有效,好像我在它显示为对象的构造函数中提醒实例。出于某种原因,当调用tokenHandler回调时,this.api突然未定义..任何想法为什么? JavaScript中的OOP非常令人沮丧...

3 个答案:

答案 0 :(得分:1)

当你这样做时

this.pushNotification.register(
    this.tokenHandler,
    this.errorHandler, ...);

您实际上是在传递函数对象tokenHandler,并且它不知道它已绑定到当前对象。因此,当register函数调用它时,因为它没有绑定到任何对象,JavaScript会将全局对象作为this传递(在严格模式下它将传递undefined)。为避免这种情况,您需要使用Function.prototype.bind这样的

显式绑定当前对象和函数对象
this.pushNotification.register(
    this.tokenHandler.bind(this),
    this.errorHandler.bind(this), ...);

答案 1 :(得分:1)

问题在于:

this.tokenHandler

只是一个函数本身,函数不知道它属于哪里以及它的上下文应该是什么。要解决此问题,您可以应用以下内容:

var self = this;
this.pushNotification.register(
    function (token) {
        self.tokenHandler(token);
    },

使用闭包将确保使用tokenHandler上下文调用self,这是Push的实例

答案 2 :(得分:0)

这是因为javascript中的作用域是在函数级别完成的。

在这个代码的和平中:

function Push(apiInstance) {
    this.api = apiInstance; // If I alert() here this is a valid object
}

"这" - 是Push函数的范围。所以,你可以尝试下一步:

var api = {};
function Push(apiInstance) {
    api = apiInstance; // If I alert() here this is a valid object
    this.pushNotification = window.plugins.pushNotification;

    if ( device.platform == 'android' || device.platform == 'Android' )
    {
        this.pushNotification.register(
            this.successHandler,
            this.errorHandler, {
                "senderID":"",
                "ecb":"onNotificationGCM"
            });
    }
    else
    {
        this.pushNotification.register(
            this.tokenHandler,
            this.errorHandler, {
                "badge":"true",
                "sound":"true",
                "alert":"true",
                "ecb":"onNotificationAPN"
            });
    }
}

Push.prototype.tokenHandler = function (token) {
    api.registerDevice(token); // Suddenly this.api is undefined
};

var push = new Push(/* in my production code this is a valid object */);

在这段代码中,api - 变量不在函数范围内,而是在"全局范围"用于推送功能。