Javascript中的范围错误。在该对象的不同方法中调用方法

时间:2013-06-12 13:33:04

标签: javascript scope prototypejs this

我有一个可变的时间记录。

var timeKeep;

我这样定义:

timeKeep = Class.create({
  initialize: function() {
    this.initObservers();
  },

  initObservers: function() {
    $$('input').each( function(el) {
      el.observe('keypress', function(ev) {
        // the key code for 'enter/return' is 13
        if(ev.keyCode === 13){
          timeKeep.submit();
              // Uncaught TypeError: Object function klass() {
              // this.initialize.apply(this, arguments);
              // } has no method 'submit'
        }
      });
    });
  },

  submit: function() {
    alert('Submitted!');
  }
})

我得到的错误在它出现的行下面被注释掉了。这与我认为在不同范围内调用timeKeep方法有关吗?

在foreach语句中调用timeKeep.method()是否有问题?

3 个答案:

答案 0 :(得分:1)

问题在于你的OOP风格。使用闭包,以便调用类的当前实例

  initObservers: function () {
      var that = this;
      $$('input')
          .each(function (el) {
              el.observe('keypress', function (ev) {
                  // the key code for 'enter/return' is 13
                  if (ev.keyCode === 13) {
                      that.submit();
                  }
              });
          });
  },

您还可以查看bind

  initObservers: function() {
      var submit = this.submit.bind(this);
      $$('input')
          .each(function (el) {
              el.observe('keypress', function (ev) {
                  // the key code for 'enter/return' is 13
                  if (ev.keyCode === 13) {
                      submit();
                  }
              });
          });
  },

答案 1 :(得分:1)

您假设Class.create返回您正在定义的类型的对象的实例,但不是,它返回一个构造函数,用于创建您正在定义的类的实例。

您可以将新关键字添加到作业中,然后您将及时获得所需内容:

timeKeep = new Class.create({
...
})()

答案 2 :(得分:0)

根据建议 - 使用Function#bind()将解决您的问题,但有一种更简洁的方法,以便您可以继续在类范围内使用this

另请参阅invoke()方法,因为这是使用它的绝佳机会。 $$()返回一个元素列表,如果你想对所有元素执行相同的函数,invoke()将处理迭代列表。

timeKeep = Class.create({
  initialize: function() {
    this.initObservers();
  },

  initObservers: function() {
    $$('input').invoke('observe','keypress',function(ev) {
      // the key code for 'enter/return' is 13
      if(ev.keyCode === 13){
        timeKeep.submit();
        // Uncaught TypeError: Object function klass() {
        // this.initialize.apply(this, arguments);
        // } has no method 'submit'
      }
//Add the bind method to the closure to bind 'this' inside that function scope
//to 'this' of the class
//the binding will allow you to call this.submit() instead of timeKeep.submit
//as well as access any of the class properties and methods inside this closure
    }.bind(this));
  } ,

  submit: function() {
    alert('Submitted!');
  }
});

观察员http://api.prototypejs.org/dom/Event/observe/上的PrototypeJS文档 - 查看标题使用实例方法作为处理程序