---
# System prepended metadata

title: 閉包題目補充

---

#    閉包題目補充

閉包:
1.發生在execuation context 的 creation phase
2.在function execuation context,若一變數沒有在函式中被宣告,會向外查找外層的變數
(有權訪問另一個函式作用域中變數的函式)

## [通過閉包返回區域變數]
[閉包調用方式01]
```+
function sayHi() {
    let name = 'coco';
    return function () {
        return name + " says hi";
    }
}

console.log(sayHi()());
```
[閉包調用方式02]
```+
function sayHi() {
    let name = 'coco';
    return function () {
        return name + " says hi";
    }
}

let s = sayHi();
console.log(s());
```
## [閉包累加題目們]
**[01以全域變數進行累加]**
```+
let age = 100;
function getAge() {
     age++;
}
getAge();
console.log(age);
getAge();
console.log(age);
```
**[02以區域變數進行累加]**
```+
function getAge() {
     let age = 100;
     age++;
     return age;
 }
 console.log(getAge());
 console.log(getAge());
 //以局部變數無法累加 因為每執行一次 100被初始化了
```
**[03結合匿名函式&閉包進行累加]**
```+
 function getAge() {
     let age = 100;
     return function () {
         age++;
         return age;
     }
 }

 console.log(getAge()());
 console.log(getAge()());
 //這樣就調用死了不會累加 重複調用了getAge() 還是會初始化

var s = getAge(); 
console.log(s());
console.log(s());
//普通函式getAge()只執行一遍 重複呼叫內層匿名函式即可

```
 
## [循環裡的閉包&匿名函式的取值問題們]
[01]
```+
function box() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr[i] = function () {
            return i;
        };
    }

    return arr;
}
var b = box();
for (var i = 0; i < 5; i++) {
    console.log(b[i]());
}
```
[題目解釋](https://1drv.ms/p/s!Ar8ou6d-D88lgTvX8U4HqbQPGjs9?e=STtpbD)

[02 通過匿名函式及時自我執行]
```+
function box() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr[i] = (function (num) {
            return num;
        })(i);
    }
    return arr;
}

var b = box();
for (var i = 0; i < 5; i++) {
    console.log(b[i]);
}
```
[03]
```+
function box() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr[i] = (function (num) {
            return function () { 
                return num;
            };
        })(i);
    }

    return arr;
}

var b = box();
for (var i = 0; i < 5; i++) {
    console.log(b[i]());
}

```

[04]
```+
function box() {
    var arr = [];
    for (let i = 0; i < 5; i++) {
        arr[i] = function () {
            return i;
        };
    }

    return arr;
}
var b = box();
for (var i = 0; i < 5; i++) {
    console.log(b[i]());
}
```

## [結合閉包&this的問題們]
[01:this指定的對象是基於函數執行的環境所決定的,但**閉包中的this指向全域**] (可背!)
```+
var user="the window";
var box={
    user:"the box",
    getUser:function(){
        return function(){
            return this.user;
        }
    }
}

console.log(box.getUser()());
```
[02 讓閉包指向區域變數方法1:對象冒充]
```+
var user="the window";
var box={
    user:"the box",
    getUser:function(){
        return function(){
            return this.user;
        }
    }
}
console.log(box.getUser().call(box));
```
[03 讓閉包指向區域變數方法2:在作用域鏈上調整]
```+
var user="the window";
var box={
    user:"the box",
    getUser:function(){
        //這裡this的作用域指向box
        var that = this;
        return function(){
            //這裡this的作用域指向window
            return that.user;
        }
    }
}

console.log(box.getUser()());
```
## [閉包通常和匿名函式結合-匿名函式常見型態]
```+
//1.把匿名函數賦值給變數
var hi = function () {
    return 'hi';
};

console.log(hi());

//2.通過自我執行來執行匿名函數
(function () {
    console.log("hi");
})();

//3.把匿名函數自我執行的返回值賦值給變數
var hi = (function () {
    return 'hi';
})();

console.log('hi');

//4.匿名函數自我執行傳參數
(function (age) {
    console.log(age);
})(100);
```

## 參考資料
很推薦的文章:
[談談JavaScript中closure的概念系列1-4]
https://pjchender.blogspot.com/2016/05/javascriptclosures.html
https://pjchender.blogspot.com/2016/05/javascriptclosure.html
https://pjchender.blogspot.com/2016/05/javascriptclosure-part-3.html
https://pjchender.blogspot.com/2016/05/javascriptclosure-part-4.html
[codepen](https://codepen.io/phoebe4561/pen/LYybaOL?editors=0012)

## 面試練習題們:
(可以自己練習)
[01]
```+
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));
console.log(add10(2));

```

[02]
```+
let x = 1
function A(y) {
  let x = 2
  function B(z) {
    console.log(x + y + z)
  }
  return B
}
let C = A(2)
C(3)
```

[03]
```+

let x = 5
function fn(x) {
  return function (y) {
    console.log(y + (++x))
  }
}
let f = fn(6)
f(7)
fn(8)(9)
f(10)
console.log(x)
```
[04]
```+
let a = 0,
  b = 0
function A(a) {
  A = function (b) {
    console.log(a + b++)
  }
  console.log(a++)
}
A(1)
A(2)

```

![](https://i.imgur.com/OCvSafw.png)



答案:
[1]7,12
[2]7
[3]14,18,18,5
[4]1,4


```+
let myName="wilson";
function sayHi(){
    let myName = "coco";
    console.log(myName);

    function sayHi2(){
        console.log(myName);
    }
    sayHi2();
}

sayHi();
```