# 閉包題目補充
閉包:
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)
```

答案:
[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();
```