const str = 'foobarfoo'; console.log(str.replaceAll(/foo/, '')); // TypeError: String.prototype.replaceAll called with a non-global RegExp argument console.log(str.replaceAll(/foo/g, '')); // bar
Posted onEdited onInjavascript Symbols count in article: 925Reading time ≈3 mins.
Hoisting in JavaScript
JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, classes, or imports to the top of their scope, prior to execution of the code.
Variable Hoisting
1 2
console.log(a); // undefined var a = 1;
The above code is equivalent to:
1 2 3
var a; console.log(a); // undefined a = 1;
注意变量提示只提升到它所在的作用域的顶部,而不是全局作用域的顶部。
1 2 3 4 5 6 7 8 9
functionouter() { console.log(a); // ReferenceError: a is not defined functioninner() { console.log(a); // undefined var a = 1; } inner(); } outer();
The above code is equivalent to:
1 2 3 4 5 6 7 8 9 10 11
functionouter() { console.log(a); // ReferenceError: a is not defined functioninner() { var a; // a is hoisted to the top of its enclosing function `inner`. console.log(a); // undefined a = 1; }
const x = 1; { console.log(x); // ReferenceError: Cannot access 'x' before initialization const x = 2; }
如果我们把const x = 2;注释掉,那么代码就可以正常运行,此时x使用的是外层的x。这说明const x = 2;是被提升的(进而掩盖了外层的x),只是在TDZ中不能访问。
1 2 3 4 5
const x = 1; { console.log(x); // 1 // const x = 2; }
Temporal dead zone (TDZ)
A variable declared with let, const, or class is said to be in a "temporal dead zone" (TDZ) from the start of the block until code execution reaches the place where the variable is declared and initialized. 下面的代码中,
1 2 3 4 5 6 7 8 9 10 11 12
// Temporal dead zone (TDZ), TDZ 从block开始的地方开始,到其定义的地方结束。 // 在TDZ中访问let定义的变量会产生ReferenceError。 // 而var定义的变量则不存在此问题,因为var有hoisting(变量提升) { // TDZ starts at beginning of scope console.log(bar); // undefined console.log(foo); // ReferenceError var bar = 1; let foo = 2; // End of TDZ (for foo) const xxx = 3; }
<body> <divid="progress"></div> <buttononclick='alert("Hello, world!")'>show alert</button> <script> let i = 0; functioncount() { // do a piece of the heavy job (*) do { i++; progress.innerHTML = i; } while (i % 1e3 != 0); if (i < 1e7) { setTimeout(count); } } count(); </script>
上面代码的执行顺序是这样的:
执行同步代码,先处理1000个数字。
i < 1e7, 表示还有数字需要处理,所以调用setTimeout,将count函数放到宏任务队列中。
对于Promise需要特别注意:Promise本身是同步代码,但是其.then, .catch, .finally对应的回调函数是异步代码。对于queueMicrotask,它是一个新的API,用于将一个微任务添加到微任务队列中。(If we’d like to execute a function asynchronously (after the current code), but before changes are rendered or new events handled, we can schedule it with queueMicrotask.)
解析:会输出’promise one running…’, 虽然Promise.all会在任何一个promise reject之后立即reject,但是剩下的promise还是会继续执行,直到resolve或者reject。注意这就是promise的不可取消性,如何要取消,请使用RxJS中的observable。
解析:会输出’promise one running…’, 虽然Promise.all会在任何一个promise reject之后立即reject,但是剩下的promise还是会继续执行,直到resolve或者reject。注意这就是promise的不可取消性,如何要取消,请使用RxJS中的observable。