You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: Fix misleading lexical claim in setInterval docs to match the actual example (mdn#43465)
* fix: Fix misleading lexical claim in setInterval docs to match the actual example
* feat: Add lexical example with contrast and fix incorrect comment in setInterval docs
* Rewrite
---------
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
Copy file name to clipboardExpand all lines: files/en-us/web/api/window/setinterval/index.md
+59-23Lines changed: 59 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -113,37 +113,73 @@ While this pattern does not guarantee execution on a fixed interval, it does gua
113
113
114
114
### Functions are called with the global `this`
115
115
116
-
Methods or functions passed to `setInterval()` do not run in the same execution context as `setInterval()`, and hence do not have the same [`this`](/en-US/docs/Web/JavaScript/Reference/Operators/this) as the function that called `setInterval()`.
117
-
Instead the called function has a `this` keyword set to the `window` (or `global`) object.
116
+
The functions passed to `setInterval()` is run with normal function call semantics for determining the reference of [`this`](/en-US/docs/Web/JavaScript/Reference/Operators/this).
118
117
This problem is explained in detail in the [JavaScript reference](/en-US/docs/Web/JavaScript/Reference/Operators/this#callbacks).
119
118
120
-
The following example demonstrates how this can cause unexpected behavior (using `setTimeout()` instead of `setInterval()`, but the problem applies to both timers):
119
+
For non-arrow functions, the `this` context is set to the [`globalThis`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) (an alias for [`window`](/en-US/docs/Web/API/Window/window) in browsers) object.
121
120
122
-
```js
123
-
myArray = ["zero", "one", "two"];
124
-
125
-
myArray.myMethod=function (sProperty) {
126
-
alert(arguments.length>0?this[sProperty] :this);
127
-
};
128
-
129
-
myArray.myMethod(); // prints "zero,one,two"
130
-
myArray.myMethod(1); // prints "one"
131
-
setTimeout(myArray.myMethod, 1000); // Alerts "[object Window]" after 1 second
132
-
setTimeout(myArray.myMethod, 1500, "1"); // Alerts "undefined" after 1.5 seconds
133
-
```
121
+
The following example demonstrates how this can cause unexpected behavior. Here, when we pass the method `counter.count` directly to `setInterval()`, the `this` context is lost, and the method is called on the global object instead of the `Counter` instance, resulting in a `TypeError` when the `count` method tries to access `this`:
134
122
135
-
You can use [arrow functions](/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) to adopt the `this` of the function in which `setTimeout()` is called (arrow functions have a lexical `this`).
setTimeout(() =>myArray.myMethod(), 1000); // Alert "zero,one,two" after 1 second
141
-
setTimeout(() =>myArray.myMethod(1), 1500); // Alert "one" after 1.5 seconds
142
-
setTimeout(() =>myArray.myMethod(2), 3000); // Alert "one" after 3 seconds
136
+
counter.count("foo"); // Successfully adds "foo" to the map
137
+
setInterval(counter.count, 1000, "bar");
138
+
// TypeError: Cannot read properties of undefined (reading 'set')
143
139
```
144
140
145
-
You might also use the [`Function.prototype.bind()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) method, which lets you specify the value that should be used as `this` for all calls to a given function.
146
-
That lets you bypass problems where it's unclear what `this` will be, depending on the context from which your function was called.
141
+
To work around this, you must make sure that the function passed to `setInterval` has the correct `this` context. There are three main ways to do this:
142
+
143
+
1. If you want to explicitly specify the `this` context, instead of passing the method directly, wrap the method call in another anonymous function that explicitly calls the method with the correct context:
144
+
145
+
```js
146
+
setInterval(() =>counter.count("bar"), 1000);
147
+
setInterval(function () {
148
+
counter.count("bar");
149
+
}, 1000);
150
+
```
151
+
152
+
2. If you want to use the `this` context of the code that calls `setInterval()`, always use an arrow function, which inherits the `this` context of its enclosing scope:
153
+
154
+
```js example-bad
155
+
classCounter {
156
+
// …
157
+
repeatedCount(item) {
158
+
// BAD: the `this` context is lost in the callback
3. If you want to avoid extra function wrappers (which increase memory usage) while explicitly specifying the `this` context, you can use the [`Function.prototype.bind()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) method to create a new function with the correct `this` context:
Copy file name to clipboardExpand all lines: files/en-us/web/api/window/settimeout/index.md
+58-37Lines changed: 58 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -111,53 +111,74 @@ If the order that an asynchronous method completes does matter, then you can use
111
111
112
112
### Functions are called with the global `this`
113
113
114
-
Methods or functions passed to `setTimeout()` do not run in the same execution context as `setTimeout()`, and hence do not have the same [`this`](/en-US/docs/Web/JavaScript/Reference/Operators/this) as the function that called `setTimeout()`.
115
-
Instead the called function has a `this` keyword set to the `window` (or `global`) object.
114
+
The functions passed to `setTimeout()` is run with normal function call semantics for determining the reference of [`this`](/en-US/docs/Web/JavaScript/Reference/Operators/this).
116
115
This problem is explained in detail in the [JavaScript reference](/en-US/docs/Web/JavaScript/Reference/Operators/this#callbacks).
117
116
118
-
The following example demonstrates how this can cause unexpected behavior:
117
+
For non-arrow functions, the `this` context is set to the [`globalThis`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) (an alias for [`window`](/en-US/docs/Web/API/Window/window) in browsers) object.
You can use a wrapper function, such as an [arrow function](/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), to adopt the `this` of the function in which `setTimeout()` is called (arrow functions have a lexical `this`).
133
-
134
-
You can test this with the following code:
119
+
The following example demonstrates how this can cause unexpected behavior. Here, when we pass the method `counter.count` directly to `setTimeout()`, the `this` context is lost, and the method is called on the global object instead of the `Counter` instance, resulting in a `TypeError` when the `count` method tries to access `this`:
135
120
136
121
```js
137
-
// Arrow function callback
138
-
setTimeout(() =>myObject.log(), 2000); // myProperty: 12 after 2 seconds
You might also use the [`Function.prototype.bind()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) method, which lets you specify the value that should be used as `this` for all calls to a given function.
147
-
That lets you bypass problems where it's unclear what `this` will be, depending on the context from which your function was called:
myBoundMethod(); // prints "zero,one,two" because 'this' is bound to myArray in the function
156
-
myBoundMethod(1); // prints "one"
157
-
setTimeout(myBoundMethod, 1.0*1000); // still prints "zero,one,two" after 1 second because of the binding
158
-
setTimeout(myBoundMethod, 1.5*1000, "1"); // prints "one" after 1.5 seconds
134
+
counter.count("foo"); // Successfully adds "foo" to the map
135
+
setTimeout(counter.count, 1000, "bar");
136
+
// TypeError: Cannot read properties of undefined (reading 'set')
159
137
```
160
138
139
+
To work around this, you must make sure that the function passed to `setTimeout` has the correct `this` context. There are three main ways to do this:
140
+
141
+
1. If you want to explicitly specify the `this` context, instead of passing the method directly, wrap the method call in another anonymous function that explicitly calls the method with the correct context:
142
+
143
+
```js
144
+
setTimeout(() =>counter.count("bar"), 1000);
145
+
setTimeout(function () {
146
+
counter.count("bar");
147
+
}, 1000);
148
+
```
149
+
150
+
2. If you want to use the `this` context of the code that calls `setTimeout()`, always use an arrow function, which inherits the `this` context of its enclosing scope:
151
+
152
+
```js example-bad
153
+
classCounter {
154
+
// …
155
+
delayedCount(item) {
156
+
// BAD: the `this` context is lost in the callback
3. If you want to avoid extra function wrappers (which increase memory usage) while explicitly specifying the `this` context, you can use the [`Function.prototype.bind()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) method to create a new function with the correct `this` context:
### Non-number delay values are silently coerced into numbers
162
183
163
184
If `setTimeout()` is called with [_delay_](#delay) value that's not a number, implicit [type coercion](/en-US/docs/Glossary/Type_coercion) is silently done on the value to convert it to a number.
0 commit comments