在Javascript中调用对象方法时不是函数类型错误

时间:2016-05-06 16:08:54

标签: javascript oop higher-order-functions class-method

问题:

当我尝试在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工作正常。

问题:

为什么从模型调用方法时会出现此错误和/或如何解决此问题?

1 个答案:

答案 0 :(得分:3)

model.setSelection不保留对象的引用。如果您不需要支持旧浏览器,则可以将其绑定到对象:

model.setSelection.bind(model)

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

function () { model.setSelection(); }

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

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