2016-05-06 6 views
1

Проблема:не функция TypeError при вызове метода объекта в 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

Прошу прощения, но я до сих пор не совсем понимаю, и я не могу заставить его работать, используя bind, как вы предлагаете , ни каким-то другим способом я не пытался. Итак, если вы хотите передать функцию объекту, вам нужно связать все, что относится к функции или что-то в этом роде? Я немного разочарован в JavaScript, потому что это не очень приятно, если вы хотите использовать функции более высокого порядка. – Sebi

+1

Это только проблема, если вы пытаетесь передавать функции-члены самостоятельно, как вы пытаетесь сделать в setTimeout. 'setTimeout (function() {model.setSelection();}, 2000)' должен работать нормально, учитывая то, что вы вставили. –

+0

Хорошо, спасибо, я наконец получил его сейчас! Ваше решение действительно работает! – Sebi