Как объект, созданный dojo.declare, может получить доступ к своим свойствам?

У меня возникла концептуальная проблема с использованием объектов класса Dojo, созданных с помощью dojo/_base/declare.

Я создал следующий модуль:

define(["dojo/_base/declare", ....], function(declare,....){
    return declare('my.widget', null ,function(..){
     startup: function() {
       ....
       new Button({onClick: this.newItem}, newButtonNode)
     },
     newItem: function() {
       this.openDialog({}, this.saveItemCallback)
     },
     openDialog: function(item,callback){...},
     saveItemCallback: function(item){....}
    })
})

Проблема в том, что функция newItem не работает, потому что, когда она вызывается по нажатию кнопки, this указывает на виджет Button, а не на экземпляр my.widget.

Я запутался. Как я могу обратиться к экземпляру my.widget? В классах Dojo, которые я читал, текущий экземпляр доступен в разделе this.


person Danubian Sailor    schedule 16.10.2013    source источник
comment
Для функции openDialog имейте в виду, что иногда лучше вернуть Promise чем требовать обратных вызовов в качестве параметров.   -  person Darien    schedule 16.10.2013


Ответы (2)


Если вы затем хотите вызвать newItem с правильной областью действия, вы можете использовать функцию dojo/_base/lang, hitch().

define(["dojo/_base/declare", "dojo/_base/lang", ....], function(declare, lang, ....){
    return declare('my.widget', null ,function(..){
     startup: function() {
       new Button({onClick: lang.hitch(this, "newItem"}, newButtonNode)
     },
     newItem: function() {
       this.openDialog({}, this.saveItemCallback)
     },
     openDialog: function(item,callback){...},
     saveItemCallback: function(item){....}
    })
});

Функция hitch() проверит правильность ссылки this. Это звучит как настоящее волшебство, но для выполнения функции используется какое-то отражение за экранами.

Что он действительно делает, так это использует функцию Function.prototype.apply, чтобы начать волшебство. Как вы можете прочитать в этой статье он принимает контекст и параметры. Таким образом, фактически будет изменена ссылка this при выполнении newItem.

person g00glen00b    schedule 16.10.2013
comment
Хорошо, но это не проблема. Проблема в том, что для функции newItem «это» — это кнопка, а не «мой экземпляр». «myInstance» виден только в функции «запуск». - person Danubian Sailor; 16.10.2013
comment
@ЛукашЛ. починил это. Это почти то же самое, что написал Крис Хейс, но с новым синтаксисом AMD. - person g00glen00b; 16.10.2013
comment
Да, это оно! У меня до сих пор проблемы с пониманием того, что делает "заминка". - person Danubian Sailor; 16.10.2013
comment
Я отредактировал свой ответ, чтобы объяснить, что делает hitch. За экранами он использует какое-то отражение, чтобы делать магические вещи. Существует функция apply, которая позволяет вам изменить то, на что ссылается this. - person g00glen00b; 16.10.2013
comment
Тем не менее, зная, что искать, я нашел несколько вариантов использования lang.hitch в коде Dojo, поэтому ваш ответ — канонический способ делать что-то в Dojo. - person Danubian Sailor; 16.10.2013

Вы можете использовать dojo.hitch для присоединения контекста к функции:

define(["dojo/_base/declare", ....], function(declare,....){
    var myFunc = dojo.hitch(this, function() { 
       this.openDialog({}, this.saveItemCallback)
    });

    return declare('my.widget', null ,function(..){
     startup: function() {
       ....
       new Button({onClick: this.newItem}, newButtonNode)
     },
     newItem: myFunc,
     openDialog: function(item,callback){...},
     saveItemCallback: function(item){....}
    })
})

Делая это, вы фактически заявляете, что в анонимной функции, переданной dojo.hitch, this относится к первому переданному аргументу (который может быть любым объектом).

person Chris Hayes    schedule 16.10.2013
comment
При этом я получил ошибку еще до того, как объект был создан, в объявлении myFunc: «this.openDialog is undefined» - person Danubian Sailor; 16.10.2013