Клуб API Карт

Ещё раз про видимость переменных внутри modules.require

delite86
25 июля 2016, 23:52

Доброго времени суток! Прошу уделить мне минуту времени и попробовать повторно разъяснить про видимость переменных, ибо эта базовая вещь до меня с первого раза никак не дошла, и я делаю неправильно.

Взять, к примеру, Heatmap Module.

ymaps.ready(init);
function init(){
    myMap = {......};

    ymaps.modules.require(['Heatmap'], function (Heatmap) {
        heatmap = new Heatmap({}, {
            gradient: gradients[0],
            radius: radiuses[1],
            opacity: opacities[2]
        });
        heatmap.setMap(myMap);

    }); //heatmap

} //init

Работает, показывает. Нужна кнопка вкл/выкл.

Куда бы и в какой бы последовательности я ни запихнул это

 var heatmap = new ymaps.control.Button({
     data: {
         content: 'ВКЛ/ВЫКЛ'
         } 
     });

    myMap.controls.add(heatmap);

    heatmap.events.add('press', function () {
         heatmap.setMap(
         heatmap.getMap() ? null : myMap
         );
    });

Я получу разную ошибку. Либо heatmap.setMap is not a function, либо heatmap is not defined. При размещении всего этого внутри function (Heatmap) { ошибок не выдаёт до клика по кнопке, затем heatmap.setMap is not a function.

Хотя я посмотрел на этот heatmap внутри:

heatmap.events.add('press', function () {
  explain(heatmap); //смотрю в консоль
);

function explain(obj) {for (var i in obj) { console.log(i); }  console.log(obj);}

Консоль:
state
data
options
events
_itemImplementation
eventProxy
_layout
_layoutDeferred
_selected
_enabled
_toolBarButtonComponent
id_14694794915907087
_layoutCancelableCallback
_visibilityMonitor
constructor
_setupLayoutEventRules
_onClick
select
deselect
isSelected
enable
disable
isEnabled
_onStateChange
_setupSelectableEventRules
getLayout
getLayoutSync
onAddToMap
onRemoveFromMap
_setupLayout
_destroyLayout
_createLayout
_onVisibilityChange
_setVisibleState
_fireLayoutChangeEvent
getParent
setParent
getMap
createOptionManager
_onParentChange
_onMapChange

и никакого setMap не вижу.

Я очень долго мучался, и до меня никак не дошло, как сделать эту кнопку. До этого я так же бесполезно мучался с PieChart, и мучения будут бесконечны, пока я чего-то не пойму. Можно ли эту ситуацию объяснить на уровне "чайника", так сказать, ибо я уверен, что какая-то простейшая банальщина.

Конечно, я могу вместо  var heatmap= написать просто  heatmap= внутри функции, и область видимости станет глобальной, кнопка заработает, но такое решение выпилят из JS в самом ближайшем будущем, и всё сломается. Я бы хотел понять, как правильно.

4 комментария
Подписаться на комментарии к посту
Всеволод Шмыров
26 июля 2016, 12:26
Добрый день. Области видимости переменных никак не связана с modules.require. Это базовые инструмент в JS независимо от контекста использования. 
Почитайте теорию JS. https://learn.javascript.ru/functions-closures
Всеволод Шмыров,
Добрый день. Учебник JS я читаю, и буду читать очень долго, пока не усвою. В данном случае, пример или объяснение конкретного случая могло бы внести существенный вклад в общее понимание. Учебник содержит также упоминание о window (оно же без var, если не use strict), что меня дополнительно путает, потому что я теперь не знаю, вдруг я именно должен объявлять window.heatmap вместо var heatmap, как и собирался.
Я всё же уверен, что это необязательно.
Почему heatmap.setMap(myMap) внутри ymaps.modules.require работает, а внутри heatmap.events.add('press', function () { , находящемся там же строчкой ниже, уже "знаю про heatmap, но не знаю про heatmap.setMap"?
Как правильно определить событие press в этом простейшем примере, не прибегая к window.heatmap=new Heatmap({}......?
Всеволод Шмыров
26 июля 2016, 16:47
delite86,
У вас в слушателе heatmap.events.add('press' ссылает на саму кнопку, так как используется переменная с таким же названием "var heatmap = new ymaps.control.Button".
Всеволод Шмыров,
Вы правы! Тут остаётся только ладонью лицо закрыть, я превзошёл самого себя и ближайших конкурентов))) Действительно, переименовал кнопку в heatmapButton, и внутри modules.require всё прекрасно определилось с локальными переменными.