У загрузки шаблона импорта нет экземпляра объекта в `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

Другие вопросы по тегам