У загрузки шаблона импорта нет экземпляра объекта в `this` - где он?
Я поигрался с импортом html5 и JS, чтобы создать какой-то mvc, и теперь у меня проблема.
Когда я импортирую шаблон и добавляю его элементы в свой DOM и регистрирую событие, он запускается и все хорошо.Но тогда this
instance содержит шаблон importet вместо объекта, функцией свойства которого является метод привязки....:)
Важные строки для этой проблемы - чтобы понять процесс - есть комментарии рядом....
Мой вопрос: как я могу выделить родительский объект этого метода для моего self
переменная?
У меня есть контроллер родительского объекта:
var controller = function(){
};
controller.prototype.import = function(filepath, callback){
var link = document.createElement('link');
link.rel = 'import';
link.href = filepath;
//important line follows
link.onload = callback;
link.setAttribute("async", '');
document.head.appendChild(link);
return link.import;
};
controller.prototype.display = function(content, selector, target){
var new_element = content.querySelector(selector);
document.querySelector(target).appendChild(new_element.cloneNode(true));
};
И некоторый контроллер расширения xyz-controller (вот проблема):
var xyz_controller = function(){
//behold ... here the callback is defined
this.import('/templates/navigation.html', this.init_navigation);
};
xyz_controller.extends(controller);
xyz_controller.prototype.init_navigation = function(){
//if I console.log(this) it holds the imported template and not xyz_controller??
var self = this;
$('#goto-settings').on('click', function(e){
e.preventDefault();
// calls some method I removed for the example, but here was a problem - I sadly cannot call that function
self.settings("param");
return false;
});
};
Навигация помещает элементы dom в родительский документ таким образом: (В конце концов, это файл шаблона):
<script>
xyz.display(document.currentScript.ownerDocument,'#main-navigation', '#Header');
</script>
И есть также некоторый main.JS, который делает что-то с jquery и так:
//to inherit all methods from an object
Function.prototype.extends = function(object){
for(var property in object.prototype){
this.prototype[property] = object.prototype[property];
}
};
var xyz;
$( document ).ready(function(){
xyz = new xyz_controller();
});
1 ответ
В этой строке:
link.onload = callback;
Вы назначаете ссылку на функцию. Ссылки на функции обычно не навязывают что this
будет при вызове функции. Это определяется только при вызове функции.
Когда вызывается функция, значение для this
соответствует объекту, на котором вы вызываете эту функцию (я упрощаю, см. this
на MDN). В этом случае именно DOM (импортированного документа) вызывает функцию обратного вызова, и этот документ определяет значение this
,
Даже если бы вы присвоили его более прямо, как это, он все равно не использовал бы ваш объект для this
:
link.onload = this.init_navigation;
Чтобы избежать этого, явно свяжите функцию обратного вызова с this
; это отменит вышеописанное поведение:
link.onload = callback.bind(this);
Вы можете найти "Как работает ключевое слово" this "?" интересное чтение.
И вот фрагмент, который иллюстрирует, какthis
Ключевое слово ведет себя по-разному, в зависимости от того, используете ли выbind
или нет:
var msg = 'I am a window variable<br>';
var test = {
msg: 'I am a test variable<br>',
whenLoad: function () {
document.body.innerHTML += this.msg;
},
};
window.addEventListener("load", test.whenLoad); // *this* will be window
window.addEventListener("load", test.whenLoad.bind(test)); // *this* will be test