owned this note
owned this note
Published
Linked with GitHub
# 0510 Closure 閉包
###### tags: `JavaScript`
## Closure 閉包!前端面試題!
```javascript=
function square3() {
return 3 * 3
}
//五平方
function square5() {
return 5 * 5
}
function square(n) {
return n * n
}
```
```javascript=
// 回傳 n+5
function add5(n) {
return n + 5
}
// function 一等公民
const plus5 = n => n + 5
const multipleBy5 = n => n * 5
const list = [1,2,3,4,5]
// 高階函式 (higher order function) 接別人的function當作參數
function doSomething(arr, fn) {
const result = []
for (var i = 0; i < arr.length; i++) {
const a = arr[i]
const b = fn(a)
result.push(b)
}
return result
}
doSomething(list, plus5)
doSomething(list, multipleBy5)
// function plus5(1) {
// const result = []
// for (var i =0; i < 1.length; i++) {
// result.push(1[i] + 5)
// }
// return result
// }
// function multiplyBy5(1) {
// const result = []
// for (var i =0; i < 1.length; i++) {
// result.push(1[i] * 5)
// }
// return result
// }
```
```javascript=
const list = [1, 2, 3, 4, 5]
const plus5 = n => n + 5
const multiplyBy5 = n => n * 5
function doSomething(arr, callback) {
const result = []
for (var i = 0; i < arr.length; i++) {
const a = arr[i]
const b = callback(a)
result.push(b)
}
return result
}
doSomething(list, plus5)
doSomething(list, multiplyBy5)
```
- function
- 一等公民 / 高階函數 (higher order function)
- 可作為參數傳遞
- 可當成物件來做傳遞
- 可作為結果回傳
- 接函數做參數的函數 = 高階函數
- 在 Ruby 裡面
- method 不是一個物件,不能傳遞
```javascript=
// 閉包 Closure
// = 會回傳 function 的 function
// = 有記憶功能的 function
// 會記得有使用到的區域變數
function add5(n) {
return funtcion() {
return n + 5 // n 有被記得 包起來
}
}
const x = add5(10)
console.log(x) // x 是個 function
console.log(x()) // 呼叫 x 函式
```
```javascript=
function serial() {
let count = 0
let y = 1 // y 會在 function 執行以後被丟掉 (有用到才會記住)
return funtcion() {
return count += 1
}
}
const s = serial()
console.log(s) // x 是個 function
console.log(s()) //1 會記憶環境變數
console.log(s()) //2
console.log(s()) //3
console.log(s()) //4
```
## 常被講到的問題
```javascript=
for(var i =0; i < 5; i++){
console.log(i) // 印出 0, 1, 2, 3, 4
}
console.log(i) // 印出 5
```
```javascript=
for(var i =0; i < 5; i++){
setTimeout(() => {
console.log(i)
},100)
}
console.log(i)
// 5
// 5
// 5
// 5
// 5
// 5
```
```javascript=
// 閉包解法
for(var i =0; i < 5; i++){
let y = i
setTimeout(() => {
console.log(y)
},100)
}
console.log(i)
// 閉包解法二
for(var i =0; i < 5; i++){
setTimeout((y) => {
console.log(y)
},100, i)
}
console.log(i)
// 閉包解法三
function output(n) {
setTimeout(() => {
console.log(n)
},100)
}
for (var i =0; i < 5; i++) {
output(i)
}
// IIFE
for(var i =0; i < 5; i++){
// IIFE
(
(z) => {
setTimeout((y) => {
console.log(y)
},100)
)
console.log(i)
```
---
## 請解釋:
### - 為何 var 改 let 就可以運作?
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<a href="#" class="btns">1</a>
<a href="#" class="btns">2</a>
<a href="#" class="btns">3</a>
<a href="#" class="btns">4</a>
<a href="#" class="btns">5</a>
<script>
const btns = document.querySelectorAll(".btns")
for(var i = 0; i < 5; i++) {
const btn = btns[i]
btn.addEventListener("click", (e) => {
e.preventDefault()
console.log(i + 1)
})
}
</script>
</body>
</html>
```
### - 怎麼解(二)?
```javascript=
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i)
}, 100)
}
console.log(i)
```