2016-05-06 25 views
1

问题:不调用JavaScript对象方法时的函数类型错误

当我尝试调用对象方法中的JavaScript这种特别的方式,我得到以下错误:

TypeError: listener.update is not a function 

我的代码:

<html> 
<head> 
<script src="library.js"></script> 
</head> 
<body> 
<script> 

// manages listeners etc. 
function Model() { 
    var listeners = []; 

    this.addListener = function(listener) { 
     listeners.push(listener); 
    }; 

    // the model will call the listeners when "setting the selection" 
    this.setSelection = function() { 
     for (listener in listeners) 
      listener.update(); 
    }; 
}; 

// test function that will be used as update 
function moveon() { 
    var answer = confirm("Ready to move on?"); 
    if (answer) window.location = "http://google.com"; 
} 

// create a model and add a listener 
var model = new Model(); 
var listnr = {}; 
listnr.update = moveon; 
model.addListener(listnr); 
// update listener 
setTimeout(model.setSelection, 2000); // this doesn't work 
// setTimeout(listnr.update, 2000); // but this does 

</script> 
</body> 
</html> 

代码的说明:

Model对象管理着一个列表listeners,并在某些状态发生变化时调用它们的update方法。在我的例子中,当setSelection被调用时会发生这种情况。

注:

的错误不是很有见地,而且,如果我去掉最后一行,listnr.update工作正常。

问:

为什么我得到这个错误时,该方法是从模型称为和/或如何解决我这个问题?

+0

请考虑使用调试器之前去SO –

+1

如何?用调试器还能弄清楚什么?那是什么? :p – Sebi

+0

你可以检查你的侦听器对象,看看它是什么更新属性... –

回答

2

model.setSelection不保留对该对象的引用。如果你并不需要支持旧的浏览器,你可以把它绑定到对象:

model.setSelection.bind(model) 

如果您还需要担心旧的浏览器,你可以只使用一个小的匿名函数:

function() { model.setSelection(); } 

任何一种方法都会保留setSelection工作所需的对象引用。

原因listnr.update的工作原理是因为它不是同一类型的函数;你构建了一个独立的非对象函数,只需将它的引用设置为该对象,所以它工作得很好。但是,如果您使用模型进行尝试,则无法更新对象本身。

+0

我很抱歉,但我仍然不完全明白,我不能通过使用绑定你的建议,也没有以我尝试过的其他方式。 所以如果你想传递一个函数到一个对象,你需要绑定一切函数引用或类似的东西?我对JavaScript有点失望,因为如果你想使用更高阶的函数,这不是很好。 – Sebi

+1

这只是一个问题,如果你试图自己传递成员函数,就像你想在setTimeout中做的那样。 'setTimeout(function(){model.setSelection();},2000)''''应该工作得很好,因为你粘贴了什么。 –

+0

好的,谢谢我终于明白了!您的解决方案确实可行 – Sebi

相关问题