Полезная информация

Заказывай стафф с атрибутикой Mozilla и... пусть все вокруг завидуют тебе! Быть уникальным - быть с Mozilla!

№123-09-2011 15:02:07

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 7.0

JS closures: как избежать захвата ссылок на глобальные объекты?

.. в методе, передаваемом в другой контекст (с другими экземплярами тех же классов глобальных объектов)?
Происхождение вопроса. Мне понадобилось организовать разное поведение при выходе из модального диалога в зависимости от. Сделал просто передачей метода в вызываемый диалог:

Выделить код

Код:

var data={};
data.onOk=function(evt)
{
    ....
};
window.openDialog('chrome://someext/content/dialog.xul', '_blank'
    , 'chrome,dialog,modal,resizable,centerscreen',data);

и в onLoad диалога

Выделить код

Код:

document.documentElement.addEventListener("dialogaccept", data.onOk, true);

Вроде бы всё хорошо, но если при объявлении data.onOk внутри тела метода использовать глобальные объекты (window, document, etc), то при этом самом объявлении происходит захват ссылок на эти глобальные объекты, и при отработке метода мы имеем дело со ссылками на объекты, принадлежащие области объявления метода, а не области вызова:

Выделить код

Код:

var data={};
data.onOk=function(evt)
{
    Services.console.logStringMessage(document.location);
};

- при нажатии в вызванном диалоге на Ok мы в консоли получим не chrome://someext/content/dialog.xul, а chrome://someext/content/mainWindow.xul.
Разумеется, ссылки на объекты текущего контекста вызова я могу получить из передаваемого в метод event'а, но тут уже интерес чисто спортивный: можно ли как-то так объявить/привязать метод, чтобы в точке вызова, обращаясь непосредственно к глобальным объектам по имени, получить ссылки на объекты текущего контекста (контекста точки вызова)? Пытался привязывать контекст там, где метод навешивается на listener - без толку: замыкание происходит в точке объявления. А в точке объявления контекст привязывать еще не к чему: нужного контекста при объявлении просто не существует. Пытался сделать вот так:

Выделить код

Код:

(function() { Services.console.logStringMessage(document.location); }).apply();

- тоже без толку, захват по области видимости распространяется и на код внутри анонимного метода.
P.S. Еще раз повторюсь - задача представляет чисто спортивный интерес. Получить нужные ссылки вполне можно другими способами, но меня интересует именно вышеизложенный.

Отсутствует

 

№223-09-2011 17:35:25

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 7.0

Re: JS closures: как избежать захвата ссылок на глобальные объекты?

Разобрался. Если вспомнить, что привязка контекста определяет ссылку, получаемую от this, и если this ссылается на контекст окна, то мы можем получить ссылку на окно от this.window. Ну, а дальше всё становится достаточно просто:

Выделить код

Код:

data.onOk=function(evt)
{
  with (this)
  {
    Services.console.logStringMessage(document.location);
  }
};

и при навешивании листенера

Выделить код

Код:

document.documentElement.addEventListener("dialogaccept", data.onOk.bind(window), true);

Тогда все отрабатывает именно так, как требовалось.

Отсутствует

 

№324-09-2011 18:49:39

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4339
UA: Firefox 6.0

Re: JS closures: как избежать захвата ссылок на глобальные объекты?

Еще не так давно появился метод Components.utils.createObjectIn().
Правда, в данном случае это не особо полезно.


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]