very strange behaviour of settimeout function and object declaration?












0















var user = {

firstName: 'Вася',
sayHi: function(who) {
console.log(`firstname - ${this.firstName}: Привет, ${who}`);
}
}


setTimeout( function() {user.sayHi('asd')}, 2000 );


i get user.sayHi is not a function error cuz user is not defined in context of setTimeout call. afaik setTimeout context is window, and defining object via var will put that object into window object, then why it is undefined(1) ?



2. changing var to let will work ! why?



3. typing



var x = user



and changing user.sayHi to x.sayHi will work aswell !! I dont understand why. Since var x and var user are same definitions to me.
Pls explain










share|improve this question


















  • 1





    Seems to work fine: jsbin.com/doxegukana/edit?js,console,output

    – chrisg86
    Nov 22 '18 at 14:54






  • 1





    Do you have any more code beyond this that might happen to also be using the user variable? It seems that something else must be changing it so that it's no longer pointing to the object defined in this snippet.

    – James Thorpe
    Nov 22 '18 at 14:54













  • Can you reproduce the issue using snippet ?

    – Durga
    Nov 22 '18 at 14:56











  • whoops. ty James, indeed another script interfere, sorry for taking ur time :) shy

    – Anton
    Nov 22 '18 at 14:57











  • I'm guessing you are using a for loop on users (multiple). Suggest you use users.forEach instead. Something like users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

    – HMR
    Nov 22 '18 at 15:09
















0















var user = {

firstName: 'Вася',
sayHi: function(who) {
console.log(`firstname - ${this.firstName}: Привет, ${who}`);
}
}


setTimeout( function() {user.sayHi('asd')}, 2000 );


i get user.sayHi is not a function error cuz user is not defined in context of setTimeout call. afaik setTimeout context is window, and defining object via var will put that object into window object, then why it is undefined(1) ?



2. changing var to let will work ! why?



3. typing



var x = user



and changing user.sayHi to x.sayHi will work aswell !! I dont understand why. Since var x and var user are same definitions to me.
Pls explain










share|improve this question


















  • 1





    Seems to work fine: jsbin.com/doxegukana/edit?js,console,output

    – chrisg86
    Nov 22 '18 at 14:54






  • 1





    Do you have any more code beyond this that might happen to also be using the user variable? It seems that something else must be changing it so that it's no longer pointing to the object defined in this snippet.

    – James Thorpe
    Nov 22 '18 at 14:54













  • Can you reproduce the issue using snippet ?

    – Durga
    Nov 22 '18 at 14:56











  • whoops. ty James, indeed another script interfere, sorry for taking ur time :) shy

    – Anton
    Nov 22 '18 at 14:57











  • I'm guessing you are using a for loop on users (multiple). Suggest you use users.forEach instead. Something like users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

    – HMR
    Nov 22 '18 at 15:09














0












0








0








var user = {

firstName: 'Вася',
sayHi: function(who) {
console.log(`firstname - ${this.firstName}: Привет, ${who}`);
}
}


setTimeout( function() {user.sayHi('asd')}, 2000 );


i get user.sayHi is not a function error cuz user is not defined in context of setTimeout call. afaik setTimeout context is window, and defining object via var will put that object into window object, then why it is undefined(1) ?



2. changing var to let will work ! why?



3. typing



var x = user



and changing user.sayHi to x.sayHi will work aswell !! I dont understand why. Since var x and var user are same definitions to me.
Pls explain










share|improve this question














var user = {

firstName: 'Вася',
sayHi: function(who) {
console.log(`firstname - ${this.firstName}: Привет, ${who}`);
}
}


setTimeout( function() {user.sayHi('asd')}, 2000 );


i get user.sayHi is not a function error cuz user is not defined in context of setTimeout call. afaik setTimeout context is window, and defining object via var will put that object into window object, then why it is undefined(1) ?



2. changing var to let will work ! why?



3. typing



var x = user



and changing user.sayHi to x.sayHi will work aswell !! I dont understand why. Since var x and var user are same definitions to me.
Pls explain







javascript this settimeout






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 22 '18 at 14:50









AntonAnton

397




397








  • 1





    Seems to work fine: jsbin.com/doxegukana/edit?js,console,output

    – chrisg86
    Nov 22 '18 at 14:54






  • 1





    Do you have any more code beyond this that might happen to also be using the user variable? It seems that something else must be changing it so that it's no longer pointing to the object defined in this snippet.

    – James Thorpe
    Nov 22 '18 at 14:54













  • Can you reproduce the issue using snippet ?

    – Durga
    Nov 22 '18 at 14:56











  • whoops. ty James, indeed another script interfere, sorry for taking ur time :) shy

    – Anton
    Nov 22 '18 at 14:57











  • I'm guessing you are using a for loop on users (multiple). Suggest you use users.forEach instead. Something like users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

    – HMR
    Nov 22 '18 at 15:09














  • 1





    Seems to work fine: jsbin.com/doxegukana/edit?js,console,output

    – chrisg86
    Nov 22 '18 at 14:54






  • 1





    Do you have any more code beyond this that might happen to also be using the user variable? It seems that something else must be changing it so that it's no longer pointing to the object defined in this snippet.

    – James Thorpe
    Nov 22 '18 at 14:54













  • Can you reproduce the issue using snippet ?

    – Durga
    Nov 22 '18 at 14:56











  • whoops. ty James, indeed another script interfere, sorry for taking ur time :) shy

    – Anton
    Nov 22 '18 at 14:57











  • I'm guessing you are using a for loop on users (multiple). Suggest you use users.forEach instead. Something like users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

    – HMR
    Nov 22 '18 at 15:09








1




1





Seems to work fine: jsbin.com/doxegukana/edit?js,console,output

– chrisg86
Nov 22 '18 at 14:54





Seems to work fine: jsbin.com/doxegukana/edit?js,console,output

– chrisg86
Nov 22 '18 at 14:54




1




1





Do you have any more code beyond this that might happen to also be using the user variable? It seems that something else must be changing it so that it's no longer pointing to the object defined in this snippet.

– James Thorpe
Nov 22 '18 at 14:54







Do you have any more code beyond this that might happen to also be using the user variable? It seems that something else must be changing it so that it's no longer pointing to the object defined in this snippet.

– James Thorpe
Nov 22 '18 at 14:54















Can you reproduce the issue using snippet ?

– Durga
Nov 22 '18 at 14:56





Can you reproduce the issue using snippet ?

– Durga
Nov 22 '18 at 14:56













whoops. ty James, indeed another script interfere, sorry for taking ur time :) shy

– Anton
Nov 22 '18 at 14:57





whoops. ty James, indeed another script interfere, sorry for taking ur time :) shy

– Anton
Nov 22 '18 at 14:57













I'm guessing you are using a for loop on users (multiple). Suggest you use users.forEach instead. Something like users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

– HMR
Nov 22 '18 at 15:09





I'm guessing you are using a for loop on users (multiple). Suggest you use users.forEach instead. Something like users.forEach(user=>setTimeout(()=>user.sayHi('asd')))

– HMR
Nov 22 '18 at 15:09












1 Answer
1






active

oldest

votes


















-1














I'm just guessing here but think you are using timeout in a loop over users, something like:






var users = [1, 2];
for (var i = 0; i < users.length; i++) {
setTimeout(() =>
console.log(
'why 2?',
i,
'users[2] is undefined',
users[i],
),
);
}





If you use let then the variable i is block scoped, each loop gets it's own i:






var users = [1, 2];
for (let i = 0; i < users.length; i++) {
setTimeout(() =>
console.log(
'let works:',
i,
users[i],
),
);
}





As stated before; the let works because each itteration gets its own i variable but with var there is only window.i and by the time the setTimeout function executes window.i has a value of 2. Demonstrated next with an extra console.log






var users = [1, 2];
for (var i = 0; i < users.length; i++) {
setTimeout(() =>
console.log(
'now you know why 2!',
i,
'users[2] is undefined',
users[i],
),
);
}
console.log('after the loop before the timeout, and i is:',i);





Your var code probably works because you're creating a user variable that will contain the last user:






var users = [1, 2];
for (var i = 0; i < users.length; i++) {
var user = users[i]
setTimeout(() =>
console.log(
'i still is 2',
i,
'user is 2 both times as there is only one window.user',
user,
),
);
}
console.log('after the loop, user is:',user);





So as a solution you could use let but I prefer using forEach:






var users = [1, 2];
users.forEach((user) =>
setTimeout(() =>
console.log(
'no more temporary i counter variable, user is:',
user,
),
),
);
console.log('after foreach');





If I'm completely wrong then sorry for that, had to guess since you're describing a common loop problem but posted code that does not cause any of the behavior you describe.






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433472%2fvery-strange-behaviour-of-settimeout-function-and-object-declaration%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    -1














    I'm just guessing here but think you are using timeout in a loop over users, something like:






    var users = [1, 2];
    for (var i = 0; i < users.length; i++) {
    setTimeout(() =>
    console.log(
    'why 2?',
    i,
    'users[2] is undefined',
    users[i],
    ),
    );
    }





    If you use let then the variable i is block scoped, each loop gets it's own i:






    var users = [1, 2];
    for (let i = 0; i < users.length; i++) {
    setTimeout(() =>
    console.log(
    'let works:',
    i,
    users[i],
    ),
    );
    }





    As stated before; the let works because each itteration gets its own i variable but with var there is only window.i and by the time the setTimeout function executes window.i has a value of 2. Demonstrated next with an extra console.log






    var users = [1, 2];
    for (var i = 0; i < users.length; i++) {
    setTimeout(() =>
    console.log(
    'now you know why 2!',
    i,
    'users[2] is undefined',
    users[i],
    ),
    );
    }
    console.log('after the loop before the timeout, and i is:',i);





    Your var code probably works because you're creating a user variable that will contain the last user:






    var users = [1, 2];
    for (var i = 0; i < users.length; i++) {
    var user = users[i]
    setTimeout(() =>
    console.log(
    'i still is 2',
    i,
    'user is 2 both times as there is only one window.user',
    user,
    ),
    );
    }
    console.log('after the loop, user is:',user);





    So as a solution you could use let but I prefer using forEach:






    var users = [1, 2];
    users.forEach((user) =>
    setTimeout(() =>
    console.log(
    'no more temporary i counter variable, user is:',
    user,
    ),
    ),
    );
    console.log('after foreach');





    If I'm completely wrong then sorry for that, had to guess since you're describing a common loop problem but posted code that does not cause any of the behavior you describe.






    share|improve this answer






























      -1














      I'm just guessing here but think you are using timeout in a loop over users, something like:






      var users = [1, 2];
      for (var i = 0; i < users.length; i++) {
      setTimeout(() =>
      console.log(
      'why 2?',
      i,
      'users[2] is undefined',
      users[i],
      ),
      );
      }





      If you use let then the variable i is block scoped, each loop gets it's own i:






      var users = [1, 2];
      for (let i = 0; i < users.length; i++) {
      setTimeout(() =>
      console.log(
      'let works:',
      i,
      users[i],
      ),
      );
      }





      As stated before; the let works because each itteration gets its own i variable but with var there is only window.i and by the time the setTimeout function executes window.i has a value of 2. Demonstrated next with an extra console.log






      var users = [1, 2];
      for (var i = 0; i < users.length; i++) {
      setTimeout(() =>
      console.log(
      'now you know why 2!',
      i,
      'users[2] is undefined',
      users[i],
      ),
      );
      }
      console.log('after the loop before the timeout, and i is:',i);





      Your var code probably works because you're creating a user variable that will contain the last user:






      var users = [1, 2];
      for (var i = 0; i < users.length; i++) {
      var user = users[i]
      setTimeout(() =>
      console.log(
      'i still is 2',
      i,
      'user is 2 both times as there is only one window.user',
      user,
      ),
      );
      }
      console.log('after the loop, user is:',user);





      So as a solution you could use let but I prefer using forEach:






      var users = [1, 2];
      users.forEach((user) =>
      setTimeout(() =>
      console.log(
      'no more temporary i counter variable, user is:',
      user,
      ),
      ),
      );
      console.log('after foreach');





      If I'm completely wrong then sorry for that, had to guess since you're describing a common loop problem but posted code that does not cause any of the behavior you describe.






      share|improve this answer




























        -1












        -1








        -1







        I'm just guessing here but think you are using timeout in a loop over users, something like:






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'why 2?',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }





        If you use let then the variable i is block scoped, each loop gets it's own i:






        var users = [1, 2];
        for (let i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'let works:',
        i,
        users[i],
        ),
        );
        }





        As stated before; the let works because each itteration gets its own i variable but with var there is only window.i and by the time the setTimeout function executes window.i has a value of 2. Demonstrated next with an extra console.log






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'now you know why 2!',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }
        console.log('after the loop before the timeout, and i is:',i);





        Your var code probably works because you're creating a user variable that will contain the last user:






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        var user = users[i]
        setTimeout(() =>
        console.log(
        'i still is 2',
        i,
        'user is 2 both times as there is only one window.user',
        user,
        ),
        );
        }
        console.log('after the loop, user is:',user);





        So as a solution you could use let but I prefer using forEach:






        var users = [1, 2];
        users.forEach((user) =>
        setTimeout(() =>
        console.log(
        'no more temporary i counter variable, user is:',
        user,
        ),
        ),
        );
        console.log('after foreach');





        If I'm completely wrong then sorry for that, had to guess since you're describing a common loop problem but posted code that does not cause any of the behavior you describe.






        share|improve this answer















        I'm just guessing here but think you are using timeout in a loop over users, something like:






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'why 2?',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }





        If you use let then the variable i is block scoped, each loop gets it's own i:






        var users = [1, 2];
        for (let i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'let works:',
        i,
        users[i],
        ),
        );
        }





        As stated before; the let works because each itteration gets its own i variable but with var there is only window.i and by the time the setTimeout function executes window.i has a value of 2. Demonstrated next with an extra console.log






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'now you know why 2!',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }
        console.log('after the loop before the timeout, and i is:',i);





        Your var code probably works because you're creating a user variable that will contain the last user:






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        var user = users[i]
        setTimeout(() =>
        console.log(
        'i still is 2',
        i,
        'user is 2 both times as there is only one window.user',
        user,
        ),
        );
        }
        console.log('after the loop, user is:',user);





        So as a solution you could use let but I prefer using forEach:






        var users = [1, 2];
        users.forEach((user) =>
        setTimeout(() =>
        console.log(
        'no more temporary i counter variable, user is:',
        user,
        ),
        ),
        );
        console.log('after foreach');





        If I'm completely wrong then sorry for that, had to guess since you're describing a common loop problem but posted code that does not cause any of the behavior you describe.






        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'why 2?',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }





        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'why 2?',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }





        var users = [1, 2];
        for (let i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'let works:',
        i,
        users[i],
        ),
        );
        }





        var users = [1, 2];
        for (let i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'let works:',
        i,
        users[i],
        ),
        );
        }





        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'now you know why 2!',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }
        console.log('after the loop before the timeout, and i is:',i);





        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        setTimeout(() =>
        console.log(
        'now you know why 2!',
        i,
        'users[2] is undefined',
        users[i],
        ),
        );
        }
        console.log('after the loop before the timeout, and i is:',i);





        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        var user = users[i]
        setTimeout(() =>
        console.log(
        'i still is 2',
        i,
        'user is 2 both times as there is only one window.user',
        user,
        ),
        );
        }
        console.log('after the loop, user is:',user);





        var users = [1, 2];
        for (var i = 0; i < users.length; i++) {
        var user = users[i]
        setTimeout(() =>
        console.log(
        'i still is 2',
        i,
        'user is 2 both times as there is only one window.user',
        user,
        ),
        );
        }
        console.log('after the loop, user is:',user);





        var users = [1, 2];
        users.forEach((user) =>
        setTimeout(() =>
        console.log(
        'no more temporary i counter variable, user is:',
        user,
        ),
        ),
        );
        console.log('after foreach');





        var users = [1, 2];
        users.forEach((user) =>
        setTimeout(() =>
        console.log(
        'no more temporary i counter variable, user is:',
        user,
        ),
        ),
        );
        console.log('after foreach');






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 22 '18 at 15:29

























        answered Nov 22 '18 at 15:20









        HMRHMR

        13.8k113898




        13.8k113898






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433472%2fvery-strange-behaviour-of-settimeout-function-and-object-declaration%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Create new schema in PostgreSQL using DBeaver

            Deepest pit of an array with Javascript: test on Codility

            Costa Masnaga