FE-DSHUI / DSHUI

前端王者小分队读书会
4 stars 1 forks source link

《你不知道的JavaScript(上卷)》-显示创建块作用域的好处--2021-1-19分享 #10

Open AwakenedSomeone opened 3 years ago

AwakenedSomeone commented 3 years ago

1.首先简单说一下通常哪些情况会创建作用域,最常见的是函数。除此外:with、try/catch的catch内部也是一个作用域,然后就是直接{...}这种形式的方式,这样直接创建了一个块级作用域。 2.显示的创建块作用域:用{}将一段代码包裹起来,即是显示的创建了一个作用域。 在阅读的时候,了解到,显示创建块作用域的一个好处:影响垃圾回收,这个影响是好的影响,如以下代码: `function process(data) {

// todo something

} var someData = { ... };

process(someData)

var btn = document.getElementById('my_button')

btn.addEventListener('click', function click(evt){

console.log('buton click')

}) ` 这段代码中虽然除了process调用时用到了someData,但在process调用完之后并没有再用到了,应该被回收的,但是因为click函数形成了一个覆盖整个作用域的闭包,js引擎极有可能依然保存着这个结构,someData就得不到释放。如果将

var someData = { ... };

 process(someData)

```用花括号包裹起来,则显示的创建了一个作用域,就能让引擎清楚的知,这个someData没有必要保存了
3.let搭配块作用域在for循环里的优势。
如下方的代码:

for (let i = 0; i < 10; i++) { console.log(i) }

for循环头部的let不仅将i绑定到了for循环的块中,事实上它将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。类似于这样的行为:

{

let j;

for (j = 0; j < 10; j++) {

    let i = j; // 每个迭代重新绑定

    console.log(i)

}

}

这样每一个迭代里都是一个作用域,互不影响,确保使用上一个循环迭代结束时的值重新进行赋值,这样的方式联手闭包,则可以实现一些平时不能实现的东西。比如:
一般写法:
```for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i)
  }, i * 1000)
}

它会打印出什么?这个经典的例子,大家肯定都知道,会每s打印出1个10,依次答应出10个10,用let加上块作用域和闭包,就能实现我们想要的功能

  setTimeout(() => {
    console.log(i)
  }, i * 1000)
}

原因是块作用域 为每一个迭代都创建了一个i,它等同于这样的写法:


 let j = i
  setTimeout(() => {
    console.log(j)
  }, i * 1000)
}```
形成了一个闭包作用域,所以能实现依次答应0 -9的数字出来