LINUX.ORG.RU

javascript: одна глобальная переменная принимает различные значения в разных функциях?

 , ,


0

1

пилю проект на QML
логику описываю на Javascript
и вроде всё у меня получалось - до этого момента

var bombCount = 0
// много кода
function createBomb() {
    if (bombCount<3) {
        // создаю бомбу
        bombCount++
    } else console.log("CANNOT", bombCount)
}

function removeBomb(n) {
    // удаляю бомбу
    bombCount--
    console.log(bombCount)
}
при создании bombCount инкриминируется верно; при удалении в консоль всегда падает -1, бомбы не создаются больше трёх
в чём причина сего действа?



Последнее исправление: vladimirsmirnov9 (всего исправлений: 3)

У тебя изначально bombCount == -1. Когда ты создаешь бомбу их становится 0. И при удалении снова -1.

VirRaa ★★★
()
Ответ на: комментарий от VirRaa

изначально у меня bombCount == 0. когда я создаю бомбу - повторюсь - переменная увеличивается верно. но в removeBomb() я всегда имею bombCount == 0. это какая-то особая магия javascript?

vladimirsmirnov9
() автор топика

при создании bombCount инкриминируется верно; при удалении в консоль всегда падает -1, бомбы не создаются больше трёх

Насколько я помню JS, var создает локальную переменную. Поэтому в замыкании removeBomb она всегда будет равна 0. Тебе нужна глобальная переменная => попробуй без var.

annulen ★★★★★
()

это замыкания

Deleted
()

курю маны, но до сих пор ничего не понимаю. вот листинг того, что получается на данный момент:

var bomb = Qt.createComponent("Bomb.qml");
var bombCount = 0;
var maxBombs = 3;
var bombs = new Array(maxBombs);

function freeBombs() {
    var f = false;
    var i = 0;
    while (i<maxBombs&&f==false) {
        if (bombs[i]==undefined) f = true; else i++;
    }
    return i;
}

function createBomb() {
    if (bombCount<3) {
        var n = freeBombs();
        var dynamicBomb = bomb.createObject(screen, { "x": player.pos.x, "y": player.pos.y, "num": n });
        bombs[n] = dynamicBomb;
        bombCount++;
    }
}

function removeBomb(n) {
    bombs[n].destroy();
    bombCount--;
    bombs[n] = undefined;
}
мало того, что проблема с видимостью bombCount так и не решилась, так ещё и

logic.js:25: TypeError: Cannot call method 'destroy' of undefined

есть предположение, что всё это, возможно, из-за врождённого C++ головного мозга
поправьте, кому не лень

vladimirsmirnov9
() автор топика

Интересно. В браузере такой код отлично бы работал. Там var вне функций автоматически относится к глобальному объекту window. Область видимости переменной объявленной с использованием var ограничивается функцией, в которой она была объявлена, да благодаря замыканиям она также будет видна во внутренних функциях. В случае с QML глобальный объект window видно отсутствует. По идее по любому переменная объявленная вне функции должна быть глобальной... В вашем случае всё это здорово смахивает на багу QML. Может написать разрабам тикет с описанием баги? Ну, и как вариант, попробовать убрать var. Так вы явно создадите глобальную переменную, и QML не сможет вместо неё творить непонятно что.

lucentcode ★★★★★
()
Ответ на: комментарий от vladimirsmirnov9

А типы данных QML точно использует нативные для JS? Может тот же список там вовсе не родной от JS, а родной для C++ и Qt? только что я заглянул в документацию, и в этом убедился. Примитивы в QML != таковым в JS. Так что боюсь что с методами у списков вы немного погорячились...

lucentcode ★★★★★
()
Ответ на: комментарий от lucentcode

Примитивы в QML != таковым в JS. Так что боюсь что с методами у списков вы немного погорячились

какими методами каких списков? смотрел на пример samegame и пытался переделать под себя, радовался ещё, как всё легко...

vladimirsmirnov9
() автор топика

Они точно в одном неймспейсе? Посмотри так, что выводит?

var bombCount = 0
// много кода
console.log(bombCount)
function createBomb() {
//...
}

console.log(bombCount)
function removeBomb(n) {
//...
}

special-k ★★★
()
Ответ на: комментарий от special-k

почему так должно что-то выводиться? я ведь в js-файле описываю только логику - выношу туда некоторые функции, к которым потом обращаюсь из компонентов qml. то, что внутри функций - должно исполняться; глобальные переменные мне нужны для хранения информации - в данном случае о созданных бомбах.

vladimirsmirnov9
() автор топика
Ответ на: комментарий от vladimirsmirnov9

А про In QML, the global object is constant не читали? Хорошо пошутили разрабы, нечего сказать. Есть пруф, может станет понятней в чем дело. Когда вы объявили var bombCount = 0;, переменная bombCount стала константой... Отсюда и минус один постоянно при удалении одной бомбочки... От нуля отнять один ведь всегда минус один?

lucentcode ★★★★★
()
Ответ на: комментарий от vladimirsmirnov9

QML превращает глобальные переменные в константы... Так что нужен другой метод хранения информации...

lucentcode ★★★★★
()
Ответ на: комментарий от vladimirsmirnov9

почему так должно что-то выводиться?

А почему не должно, если этот код исполняется? У тебя не видна переменная bombCount там где создается функция removeBomb, только и всего. Сделай глобальный хэш, храни там все, что тебе нужно.

special-k ★★★
()
Ответ на: комментарий от special-k

как можно создать глобальный кэш, если все объекты константны? и как работает пример samegame? или вы предлагаете создать один невидимый компонент qml со множеством properties только для хранения информации?

vladimirsmirnov9
() автор топика
Ответ на: комментарий от vladimirsmirnov9

как работает пример samegame?

они очень хитро это делают. файл js, как написано в документации, помечается как

.pragma library

для того, чтобы он стал разделяемым (по умолчанию для каждого qml-компонента создаётся своя копия компонента js). далее перед игрой инициализируются все необходимые переменные.
сейчас попробую сделать так же

vladimirsmirnov9
() автор топика
Ответ на: комментарий от vladimirsmirnov9

По вашему мнению что происходит тут: var bombs = new Array(maxBombs);

/*Cannot call method 'destroy' of undefined */ — отсюда

----------------------------------------------------- Тут бомбы не все выбрасываются. use bombs.length while (i<maxBombs&&f==false) { if (bombs==undefined) f = true; else i++; } ------------------------------------------------------

alnkapa
()
Ответ на: комментарий от vladimirsmirnov9

.pragma library

всё верно, так оно заработало добавил только

function init(sc, pl) {
    screen = sc
    player = pl
    bombCount = 0;
    maxBombs = 3;
    bombs = new Array(maxBombs);
}

vladimirsmirnov9
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.