Reputation: 5390
I have the following method:
DBConnection.prototype.successHandler = function(){
console.log("DB_INFO: Schema created");
for (k in this) console.log(k);
this.setStatus(DB_STATUS_OK);
}
I call this in a transaction like this:
DBConnection.prototype.createSchema = function(){
try {
this.c2db.transaction(
function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS person(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL DEFAULT "");',
[], this.nullDataHandler, this.errorHandler);
tx.executeSql("INSERT INTO person(id, name) VALUES (NULL, 'miloud');",
[], this.nullDataHandler, this.errorHandler);
},
this.errorHandler,
this.successHandler
);
} catch(e){
console.log("DB_ERROR: error during insert with message: " + e);
return;
}
}
The problem is that I get: Uncaught TypeError: Object [object Window] has no method 'setStatus' which is clearly telling that what I am accessing is not the DBConnection
instance that I am using when I am in the success callback. How come? What is this refering to inside this callback? Is there a way to overcome this problem?
EDIT
Callbacks are defined as:
DBConnection.prototype.errorHandler = function(errorMsg){
console.log("DB_ERROR: error creating schema with msg " + errorMsg.message);
}
DBConnection.prototype.successHandler = function(){
console.log("DB_INFO: Schema created");
for (k in this) console.log(k);
this.setStatus(DB_STATUS_OK);
}
And setStatus method as
DBConnection.prototype.setStatus = function(str_status){
localStorage.setItem(db_name, str_status);
}
Thanks!
Upvotes: 0
Views: 1066
Reputation: 3472
This occurs because this
within a javascript function refers to the object that preceded it in a dot notation when called. But functions in javascript are first-class values and can be called outside of objects (or indeed, for totally different objects). For example, if obj
is an object:
obj.myFunc = function() { console.log(this) };
obj.myFunc(); // <- Here this === obj
var freeFunc = obj.myFunc; // The function is just a value, we can pass it around
freeFunc(); // <- Now this === the top object (normally window)
// Still the same function, but *how* it was called matters
What you are doing is passing the function referred to by this.successHandler
into the transaction
call, but the function doesn't know anything about the object you took it from. When it is called by transaction
it is executed without an object and this
just becomes window
.
To solve this you can use the fact that javascript has closures and wrap the function with another anonymous function:
DBConnection.prototype.createSchema = function(){
try {
var that = this;
this.c2db.transaction(
function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS person(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL DEFAULT "");',
[], this.nullDataHandler, this.errorHandler);
tx.executeSql("INSERT INTO person(id, name) VALUES (NULL, 'miloud');",
[], this.nullDataHandler, this.errorHandler);
},
this.errorHandler,
function() { that.successHandler(); }
);
} catch(e){
console.log("DB_ERROR: error during insert with message: " + e);
return;
}
}
Now successHandler
will be called with that
as this
, which is the same as the original this
.
This is a common misconception about this
but there are also lots of explanations online, just google "javascript this".
Upvotes: 2