Как использовать функцию setInterval внутри цикла for

Я написал функцию, которая генерирует цепочку, функция valueOf и контекст this постоянно обновляется новой суммой, независимо от того, сколько аргументов передается каждый раз.

/* add function */
function add() {
    "use strict";

    var args, sum, chain;

    args = Array.prototype.slice.call(arguments);
    sum = typeof this === 'number' ? this : 0;
    sum += args.reduce(function (p, n) { return p + n; }, 0);

    chain = add.bind(sum);

    chain.valueOf = function () {
        return sum;
    };

    return chain;
}

/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
var add7 = add(7);
console.log('var add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));

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

Единственным недостатком является требование strict mode, чтобы this оставался примитивным.

Вот отредактирование для поддержки обоих strict mode и нестрогий режим:

function add() {
    var args, sum, chain;

    args = Array.prototype.slice.call(arguments);

    // Number object from non-strict mode
    if (this instanceof Number) {
        sum = Number(this);
    // number primitive from strict mode
    } else if (typeof this === 'number') {
        sum = this;
    // initial call to add
    } else {
        sum = 0;
    }

    sum += args.reduce(function (p, n) { return p + n; }, 0);

    chain = add.bind(sum);

    chain.valueOf = function () {
        return sum;
    };

    return chain;
}
29
задан isherwood 7 January 2015 в 16:50
поделиться

6 ответов

Итак, несколько вещей:

  1. Самое главное, что функция обратного вызова, которую вы передали setInterval(), поддерживает ссылку на x, а не значение снимка x, так как существовал во время каждой конкретной итерации. Таким образом, поскольку x изменяется в цикле, оно также обновляется в каждой из функций обратного вызова.
  2. Кроме того, for...in используется для перечисления свойств объекта и может вести себя неожиданно при использовании на массивах.
  3. Более того, я подозреваю, что вы действительно хотите setTimeout() , а не setInterval() .

Вы можете передать аргументы в функцию обратного вызова, предоставив дополнительные аргументы для setTimout():

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

Числа будут передаваться по значению, а не по ссылке. Вот пример:

var list = [1,2,3,4];

for (var x = 0, ln = list.length; x < ln; x++) {
  setTimeout(function(y) {    
    console.log("%d => %d", y, list[y] += 10);
  }, x * 500, x); // we're passing x
}
38
ответ дан canon 7 January 2015 в 16:50
поделиться

var list = [1, 2, 3, 4, 5];

for (var i = 0, len = list.length; i < len; i += 1) {
    (function(i) {
        setInterval(function() {
            list[i] += 10;
            console.log(i + "=>" + list[i] + "\n");
        }, 5000)
    })(i);
}

Вот рабочий код:

var list = [1, 2, 3, 4, 5];

for (var i = 0, len = list.length; i < len; i += 1) {
    (function(i) {
        setInterval(function() {
            list[i] += 10;
            console.log(i + "=>" + list[i] + "\n");
        }, 5000)
    })(i);
}

Здесь индекс i хранится в анонимном функция, чтобы она не перезаписывалась последовательными циклами. Функция setInterval в вашем коде сохраняет ссылку только на последнее значение i.

39
ответ дан Akhil Aravind 7 January 2015 в 16:50
поделиться

Вам не нужно использовать цикл for с оператором setInterval. Попробуйте это:

var list = Array(...);
var x = 0;

setInterval(function() {

    if (x < list.length;) {
        list[x] += 10;
        console.log(x+"=>"+list[x]);
    }

    else return;

    x++;
}, 5000);
4
ответ дан marsei 7 January 2015 в 16:50
поделиться

Я не знаю, как сделать это с помощью цикла for, но этот код здесь будет распечатывать каждый элемент в массиве через определенные интервалы времени:

function displayText(str) {
   $('.demo').append($('<div>').text(str));
}
var i = 0;

var a = [12, 3, 45, 6, 7, 10];

function timedLoop() {
setTimeout(function () {
    displayText(a[i]);
    i++;
    if(i < a.length) {
        timedLoop();
    }
}, 2000)
}

timedLoop();

Использование немного jquery, чтобы показать его в браузер.

2
ответ дан Ryan Mc 7 January 2015 в 16:50
поделиться

Если у вас есть массив JSON и jQuery, вы можете использовать:

$.each(jsonArray, function(i, obj) {
    setInterval( function() {
        console.log(i+' '+obj);
    }, 10);
});
0
ответ дан Atul Yadav 7 January 2015 в 16:50
поделиться

Вы можете комбинировать forEach и setTimeout, чтобы зациклить массив с интервалом.

let modes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let interval = 1000; //one second
modes.forEach((mode, index) => {

  setTimeout(() => {
    console.log(mode)
  }, index * interval)
})
0
ответ дан Taha A. 7 January 2015 в 16:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: