你不知道的 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
  • 自定义迭代器。
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
  • 迭代数字。
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. 模块

  • 这里有一个很容易被忽略的重要细节:import 和 export 都必须出现在使用它们的最顶层作用域。举例来说,不能把 import 或 export 放在 if 条件中。它们必须出现在所有代码块和函数的外面。

# 3. Promise

  • Promise.all([]) 将会立即完成(没有完成值),Promise.race([]) 将会永远挂起。这是一个很奇怪的不一致,因此我建议,永远不要用空数组使用这些方法。

# 4. 尾调用

  • 阮一峰 (opens new window)

  • ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。

  • 尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效。

  • arguments:返回调用时函数的参数。
  • func.caller:返回调用当前函数的那个函数。
以父之名
周杰伦.mp3