Phonegap localstorage和面向对象的JS

时间:2012-07-13 12:04:37

标签: javascript html5 cordova sqlite local-storage

我有以下方法:

DBConnection.prototype.successHandler = function(){
  console.log("DB_INFO: Schema created");
  for (k in this) console.log(k);
  this.setStatus(DB_STATUS_OK);
}

我在这样的交易中称之为:

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

问题是我得到:未捕获TypeError:对象[对象窗口]没有方法'setStatus'这清楚地告诉我正在访问的不是DBConnection实例那个我在成功回调时使用。怎么会?这个回调里面的内容是什么?有没有办法克服这个问题?

修改

回调定义为:

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

将setStatus方法设为

DBConnection.prototype.setStatus = function(str_status){
  localStorage.setItem(db_name, str_status);
}

谢谢!

1 个答案:

答案 0 :(得分:2)

这是因为javascript函数中的this在调用时以点表示法引用其前面的对象。但是javascript中的函数是一等值,可以在对象之外调用(或者实际上,对于完全不同的对象)。例如,如果obj是对象:

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

您正在做的是将this.successHandler引用的函数传递给transaction调用,但该函数对您从中获取的对象一无所知。当transaction调用它时,它会在没有对象的情况下执行,而this只会变为window

要解决此问题,您可以使用javascript具有闭包的事实,并使用另一个匿名函数包装该函数:

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

现在successHandler将使用that作为this进行调用,该this与原始this相同。

这是一个关于{{1}}的常见误解,但网上也有很多解释,只是google“javascript this”。