你不知道的 JS(下)
coderljw 2024-10-13 大约 2 分钟
# 1. 迭代器
- 每次在这个 arr 值上调用位于 Symbol.iterator 的方法时,都会产生一个全新的迭代器。多数结构都是这么实现的,包括所有 JavaScript 内置数据结构。
var arr = [1, 2, 3]
var it = arr[Symbol.iterator]()
it.next() // { value: 1, done: false }
it.next() // { value: 2, done: false }
it.next() // { value: 3, done: false }
it.next() // { value: undefined, done: true }
1
2
3
4
5
6
2
3
4
5
6
- 自定义迭代器。
var Fib = {
[Symbol.iterator]() {
var n1 = 1,
n2 = 1
return {
// 使迭代器成为iterable
[Symbol.iterator]() {
return this
},
next() {
var current = n2
n2 = n1
n1 = n1 + current
return { value: current, done: false }
},
return(v) {
console.log('Fibonacci sequence abandoned.')
return { value: v, done: true }
},
}
},
}
for (var v of Fib) {
console.log(v)
if (v > 50) break
}
// 1 1 2 3 5 8 13 21 34 55
// Fibonacci sequence abandoned.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- 迭代数字。
if (!Number.prototype[Symbol.iterator]) {
Object.defineProperty(Number.prototype, Symbol.iterator, {
writable: true,
configurable: true,
enumerable: false,
value: function iterator() {
var i,
inc,
done = false,
top = +this
// 正向还是反向迭代?
inc = 1 * (top < 0 ? -1 : 1)
return {
// 使得迭代器本身成为iterable!
[Symbol.iterator]() {
return this
},
next() {
if (!done) {
// 初始迭代总是0
if (i == null) {
i = 0
}
// 正向迭代
else if (top >= 0) {
i = Math.min(top, i + inc)
}
// 反向迭代
else {
i = Math.max(top, i + inc)
}
// 本次迭代后结束?
if (i == top) done = true
return { value: i, done: false }
} else {
return { done: true }
}
},
}
},
})
}
for (var i of 3) {
console.log(i)
}
// 0 1 2 3
[...-3] // [0,-1,-2,-3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 2. 模块
- 这里有一个很容易被忽略的重要细节:import 和 export 都必须出现在使用它们的最顶层作用域。举例来说,不能把 import 或 export 放在 if 条件中。它们必须出现在所有代码块和函数的外面。
# 3. Promise
- Promise.all([]) 将会立即完成(没有完成值),Promise.race([]) 将会永远挂起。这是一个很奇怪的不一致,因此我建议,永远不要用空数组使用这些方法。
# 4. 尾调用
ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。
尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。
- arguments:返回调用时函数的参数。
- func.caller:返回调用当前函数的那个函数。