1

So what I want to do is console.log a specific element of my array of three nodes.

const sentinel = document.querySelectorAll('.sentinel');

    sentinel.forEach(function(element, index){
    setInterval(function(element) {

        if(index === 0){
            console.log(element);
        }

    }, 3000);
});

I've googled, and I've found this post: Get a specific element within forEach loop, which does ask the same question. However, when I console log the element I expect to get the node on the 0 index. However, I get a null element.

  • 6
    Remove the `element` parameter from the `setInterval` callback – adiga Jan 04 '20 at 12:11
  • Have a look at the documentation for [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval). There it is mentioned how you can pass something to the callback invoked by `setInterval()` (which in this case is not necessary because it's in a `.forEach()`) – Andreas Jan 04 '20 at 12:14

2 Answers2

2

You can remove element from setInterval because inner function setInterval has an access to the variables of outer function such as element. Such behavior is called closure.

In addition, it is possible to use arrow functions to make shorter and cleaner your code. Moreover, arrow functions:

An arrow function does not have its own this. The this value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules.

sentinel.forEach((element, index) => {
   setInterval(() =>{

    if (index === 0){
        console.log(element);
    }

}, 3000);
StepUp
  • 36,391
  • 15
  • 88
  • 148
  • The callback can get arguments. It needs to be passed after the delay parameter to `setInterval` – adiga Jan 04 '20 at 12:13
  • 4
    What do arrow functions have to do with the problem/answer? – Andreas Jan 04 '20 at 12:15
  • _"You can remove `element` from `setInterval`"_ - Why? – Andreas Jan 04 '20 at 12:15
  • Thanks! This fixed the problem. Also thanks for the heads up with arrow functions. Might be a cleaner way to do it! – Dario Sanchez Martinez Jan 04 '20 at 12:19
  • 1
    Better but I still miss an explanation why just using `element` works. But why the quote on `this` for arrow functions? Neither you nor OP use `this` anywhere. And if you're already adding unrelated stuff then also add a link to the question why you can not always simply exchange a `function() { ... }` with an arrow function. – Andreas Jan 04 '20 at 12:25
  • @Andreas 1.*I still miss an explanation why just using element works* Because inner function `setInterval` has an access to the variables of outer function such as `element`. Such behavior is called closure 2. *But why the quote on this for arrow functions?* This quote is additional info to describe important feature of arrow functions – StepUp Jan 04 '20 at 12:32
1

So actually you need to bind element into setInterval function

const sentinel = document.querySelectorAll('.sentinel');

sentinel.forEach(function(element, index){
    (function (_element, _index){
        setInterval(function() {

           if(_index === 0){
             console.log(_element);
           }

        }, 3000);
    })(element, index);
});
HoangHieu
  • 2,802
  • 3
  • 28
  • 44
  • 1
    There is no need for IIFE here. You can pass arguments to the callback from `setInterval` itself. Anything passed after 3000 (delay parameter), will be used in the callback. So, `setInterval(function (e, i) {... }, 3000, element, index)` should work. [Documentation](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval#Example_1_Basic_syntax) – adiga Jan 04 '20 at 13:23