我对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,知道我是否能充分解释这一点,所以我也可以对此大吼大叫。
答案 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
,_.bind
,Function.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
这适用于应用程序控件从一个上下文移动到另一个上下文的地方,例如:骨干视图到下划线函数以及回到回调函数等。