Почему мой шар (объекты) не сокращается/исчезает?

http://jsfiddle.net/goldrunt/jGL84/42/ это из строки 84 в этом скрипте JS. Существует 3 различных эффекта, которые могут быть применены к шарам, раскомментируя строки 141-146. Эффект "отказов" работает так, как должен, но эффект "asplode" ничего не делает. Должен ли я включать функцию "усадки" внутри функции asplode?

// balls shrink and disappear if they touch
var shrink = function(p) {
    for (var i = 0; i < 100; i++) {
        p.radius -= 1;
    }
    function asplode(p) {
        setInterval(shrink(p),100);
        balls.splice(p, 1);
    }
}

Ответ 1

В вашем коде несколько проблем.

Во-первых, в вашем определении:

var shrink = function(p) {
    for (var i = 0; i < 100; i++) {
        p.radius -= 1;
    }

    function asplode(p) {
         setInterval(shrink(p),100);
        balls.splice(p, 1);
    }
}

asplode является локальным для области внутри shrink и поэтому недоступен для кода в update, где вы пытаетесь его вызвать. Область JavaScript основана на функциях, поэтому update не может видеть asplode, поскольку она не находится внутри shrink. (В вашей консоли вы увидите сообщение об ошибке: Uncaught ReferenceError: asplode is not defined.)

Сначала вы можете вместо этого перемещать asplode вне shrink:

var shrink = function(p) {
    for (var i = 0; i < 100; i++) {
        p.radius -= 1;
    }
}

function asplode(p) {
     setInterval(shrink(p),100);
     balls.splice(p, 1);
}

Однако у вашего кода есть еще несколько проблем, выходящих за рамки этого вопроса:

  • setInterval ожидает функцию. setInterval(shrink(p), 100) вызывает setInterval, чтобы получить возвращаемое значение с немедленным вызовом shrink(p). Вероятно, вы хотите

    setInterval(function() { shrink(p) }, 100)
    
  • Ваш код for (var i = 0; i < 100; i++) { p.radius -= 1; }, вероятно, не делает то, что вы думаете. Это немедленно приведет к операции декремента 100 раз, а затем визуально покажет результат. Если вы хотите повторно отобразить мяч при каждом новом размере, вам нужно будет выполнить каждый отдельный декремент внутри отдельного обратного вызова времени (например, операцию setInterval).

  • .splice ожидает числовой индекс, а не объект. Вы можете получить числовой индекс объекта с помощью indexOf:

    balls.splice(balls.indexOf(p), 1);
    
  • К тому времени, когда ваш интервал работает в первый раз, оператор balls.splice уже произошел (это произошло примерно 100 мс, если быть точным). Я предполагаю, что не то, что вы хотите. Вместо этого вы должны иметь функцию декрементирования, которая неоднократно вызывается setInterval и, наконец, выполняет balls.splice(p,1) после p.radius == 0.

Ответ 2

setInterval(shrink(p),100);

Это не делает то, что вы думаете. Это вызывает shrink, передает его p, а затем передает результат на setInterval. shrink(p) возвращает undefined, поэтому эта строка фактически не помещает ничего на интервал.

Вероятно, вы хотите:

setInterval(function(){
    shrink(p)
}, 100);