调试函数的骨干问题

时间:2014-05-10 02:25:49

标签: javascript android backbone.js cordova

我对javascript非常缺乏经验,请原谅我,如果这真的很明显......

我使用此处找到的TodoMVC示例(http://todomvc.com/architecture-examples/backbone/)作为Cordova项目的基础。我遇到的麻烦是将它与Camera和Geolocation插件相结合,我在Camera / Geolocation回调函数中调用js / views / app-view.js中的任何函数时出错。我认为这是一个上下文问题,但我不太了解javascript来修复它。

例如,TodoMVC项目使用这行代码在js \ views \ app-view.js中添加新项目:

app.todos.create(this.newAttributes());

我尝试将其与相机功能结合使用手机的相机拍照,然后添加一个新的待办事项,其中存储有照片。一切正常,除非我尝试在相机回调函数中使用上面的代码行,在底部如下:

onCameraSuccess: function(imageData) {
        // Stores image data in a hidden field to be used later. Not best method but it works
        document.getElementById('imageData').value =  "data:image/jpeg;base64," + imageData;

        // This line should create a new item
        app.todos.create(this.newAttributes());
    },

它给出了错误" Undefined不是一个函数",似乎是指" this.newAttributes()"。同样,这似乎是一个上下文问题,因为同一行几乎可以在同一个脚本中的任何其他位置工作。

OnCameraSuccess是Camera的getPicture函数的回调函数:

Camera: function() {
        navigator.camera.getPicture(this.onCameraSuccess, this.onCameraFail, { quality: 50,
            destinationType: Camera.DestinationType.DATA_URL,
            targetWidth: 250,
            targetHeight: 250,
            correctOrientation: true
        });
    },

同样,Geolocation函数需要两个回调函数,成功和错误,但我找不到一种可接受的方式来引用其他函数,这些函数没有给出TYPE_MISMATCH_ERR,表示那些不是&# 39; t功能。

onDeviceReady: function() {
        //This line calls the geolocation function and specifies the two callback functions, but it thinks they don't exist
        navigator.geolocation.watchPosition(this.onLocationSuccess, this.onLocationError, {enableHighAccuracy : true});
    },

    onLocationSuccess: function(position) {
        // map logic
    },

    onLocationError: function(error) {
        alert('code: ' +error.code+ '\n' + 'message: ' +error.message + '\n');
    },

它们位于onDeviceReady函数的正下方,但由于某种原因它无法找到它们。 this.onLocationSuccess不起作用(尽管它是如何引用它的所有其他函数),self.onLocationSuccess不起作用......再次,它似乎是一个上下文的问题,但我无法弄清楚。

有什么想法吗?我甚至不太了解javascript,知道我是否能充分解释这一点,所以我也可以对此大吼大叫。

2 个答案:

答案 0 :(得分:2)

JavaScript中this的值取决于函数的调用方式。例如,这个:

var obj = {
    f: function() { console.log(this) }
};
obj.f();

会将obj放入控制台,但是:

var obj = {
    f: function() { console.log(this) }
};
var f = obj.f;
f();
即使正在调用相同的函数,

也会(通常)将window转储到控制台中。当this行为开始使用JavaScript时,几乎所有人都会感到困惑。在您的情况下,文档没有说明this回调中getPicture的内容,因此this可能是window而不是您的对象

如果您在JavaScript中需要具有回调函数的特定this,则通常需要自行安排。一种方法是在变量中存储所需的this并使用匿名函数:

var _this = this;
navigator.camera.getPicture(
    function(imageData) { _this.onCameraSuccess(imageData) },
    ...
);

更简洁的方法(特别是当您的函数有参数时)是使用$.proxy_.bindFunction.prototype.bind或类似函数将函数绑定到所需的this几乎每个JavaScript工具包都附带的实用程序。例如,鉴于此:

var obj = {
    f: function() { console.log(this) }
};
var f1 = $.proxy(obj.f, obj);
var f2 = _(obj.f).bind(obj);
var f3 = obj.f.bind(obj);

调用f1()f2()f3()都会将obj转储到控制台中。 Underscore是Backbone的典型工具包,所以这很常见:

navigator.camera.getPicture(
    _(this.onCameraSuccess).bind(this),
    _(this.onCameraFail).bind(this),
    { ... }
);

Underscore还提供_.bindAll,这通常在initialize内用于绑定多个函数:

initialize: function() {
    _.bindAll(this, 'onCameraSuccess', 'onCameraFail');
    //...
}

然后您可以使用this.onCameraSuccess而无需担心绑定:

navigator.camera.getPicture(
    this.onCameraSuccess,
    this.onCameraFail,
    { ... }
);

_.bindAll中使用initialize可能是Backbone中最常用的方法。

答案 1 :(得分:-1)

由于您将此作为相机功能的参考传递,因此摄像机的上下文会覆盖应用程序的当前上下文。

复制当前上下文,如

var currentContext = this;
currentContext.onCameraSuccess,
currentContext.onCameraFail

这适用于应用程序控件从一个上下文移动到另一个上下文的地方,例如:骨干视图到下划线函数以及回到回调函数等。