very strange behaviour of settimeout function and object declaration?
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
|
show 2 more comments
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
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 theuser
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 likeusers.forEach(user=>setTimeout(()=>user.sayHi('asd')))
– HMR
Nov 22 '18 at 15:09
|
show 2 more comments
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
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
javascript this settimeout
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 theuser
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 likeusers.forEach(user=>setTimeout(()=>user.sayHi('asd')))
– HMR
Nov 22 '18 at 15:09
|
show 2 more comments
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 theuser
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 likeusers.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
|
show 2 more comments
1 Answer
1
active
oldest
votes
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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');
edited Nov 22 '18 at 15:29
answered Nov 22 '18 at 15:20
HMRHMR
13.8k113898
13.8k113898
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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