Попытка вызова карты (Menu.add, языки)
Здесь ваша проблема почти наверняка связана с отсутствием связанных методов JavaScript.
Установка «this» для функции определяется только во время вызова путем изучения способа получения метода. Если вы скажете одно из:
obj.method();
obj['method']();
JavaScript выберет ссылку на «obj» и установит «this = obj» внутри вызова метода. Но если вы скажете:
obj2.method= obj.method;
obj2.method();
Теперь «this» внутри функции будет obj2, , а не obj!
Аналогично, если вы выберете метод из его объекта и будете называть его объектом первого класса:
var method= obj.method;
method();
Для «this» не будет объекта, который будет установлен, поэтому JavaScript устанавливает его для глобального объекта (он же «окно» для веб-браузеров). Вероятно, это то, что происходит в вашем случае: метод «Menu.add» теряет все ссылки на своего владельца «Меню», поэтому, когда его вызывают, он, скорее всего, неосознанно записывает элементы объекта «окна» вместо меню.
Это, конечно, весьма необычно для языка ОО, и почти никогда не того, чего вы хотите, но, эй, вот как JavaScript катится. Причинение молчаливых, трудных для отладки ошибок является частью логического обоснования языка.
Чтобы обойти эту проблему, вы можете передать ссылку на объект в функцию карты, а затем использовать Function.call () / apply (), чтобы правильно установить ссылку "this":
function mapMethod(fn, obj, sequence) {
for (var i= 0; i<sequence.length; i++)
sequence[i]= fn.call(obj, sequence[i]);
}
mapMethod(Menu.add, Menu, languages)
Более общим способом было бы связать ссылки на функции вручную, используя замыкание:
function bindMethod(fn, obj) {
return function() {
fn.apply(obj, arguments)
};
}
map(bindMethod(Menu.add, Menu), languages)
Эта возможность будет встроена в будущую версию JavaScript:
map(Menu.add.bind(Menu), languages)
И эту функцию можно добавить к текущим браузерам, написав в Function.prototype.bind - действительно, некоторые платформы JS уже делают. Однако обратите внимание:
ECMAScript 3.1 обещает, что вы также сможете передавать дополнительные аргументы в bind () для выполнения частичного применения функции, которое требует немного больше кода, чем bindMethod () выше;
IE любит пропускать память, когда вы начинаете оставлять ссылки, такие как связанные методы, на объекты DOM, такие как обработчики событий.