---
# System prepended metadata

title: JS(6/10) Day 20 五倍紅寶石(第八屆共筆)(2021/7/23)
tags: [JavaScript]

---

# JS(6/10) Day 20 五倍紅寶石(第八屆共筆)(2021/7/23)
物件：
用 Object.keys (變數名稱)、Object.values (變數名稱)可印出所有 key 跟 value。
在物件裡面的函式會稱作方法，在外面就叫函式。
## 閉包(closure)：
一種特性，當使用高階函式時，可以將外層函式裡宣告的變數&值保留到內層函式使用。
```=js
//  外層函式 = a
function a() {
    var x = 123
    
    //  closure 閉包
    //  內層函式 = setTimeout
    setTimeout(() => {
        console.log(x)
    }, 1000)
}
a()
```
結論：x 本來會隨著外層的泡泡破掉而消失，但 JS 卻能把 x 一起帶到 WebAPI 排隊。

過程：(網路上統整的結果，如有寫錯還請同學更正，感謝)
一開始 JS 會先建構全域執行環境、分配記憶體給函式及變數、建構函式及宣告變數&賦值。
=> function a & setTimeout 、 var x = 123 及 console.log(x) 的 x 都會被建立起來。(console.log(x) 的 x 會因為 scope chain 的關係先在內層找有沒有宣告 x ，因為找不到所以往外層找，最後找到 var x = 123，所以內層的 x 會指向外層的 123)

再來會建構 function 的執行環境以及執行程式碼。
=> 呼叫 function a ，建構 a 的執行環境，將 x 儲存在 a 的執行環境。
=> 準備執行 setTimeout ，外層 a 的泡泡破掉，此時 var x = 123 因為一開始有被分配到記憶體，所以還會留在原地，不會跟著泡泡破掉而消失。
=> 執行 setTimeout，x 能夠指向外層的 123，不會變成not defined。

---

### 高階函式(HOF)：
很好用，= 函式製造機，可以生出函式出來。
ex:3D列印機可以印出自己出來。

## 物件導向(Object-oriented)：
其實就是生物分類法，希望把共同的特性寫在前端，讓後端的物件能直接使用前端的特性。
=> 我只要在前端寫一次，後端的東西就能夠使用，相當方便，不然如果後端的東西有100個的話就要寫100次，太累。

物件 = 屬性 + 行為
屬性：名詞
行為：動詞(function)

繼承 = 分類：可以讓子類別的東西使用上層類別(Super Class、Parent Class)的東西

建構函數：
function 如同{ }可以用來建構物件，把他當成一般物件來用可以做到以下的事。
```=js
function heroCreater(name, action) {

    const attack = () => {
        console.log(`${name}使用絕招${action}`)
    }
    return {
        name,
        action,
        attack
        //  當參數和屬性同名時，可省略值不寫
        //  原本應該長成 name: name,
    }
}
const h = heroCreater("小傑", "剪刀石頭石頭")
h.attack()
//  "小傑使用絕招剪刀石頭石頭"
console.log(h)
//  [object Object] {
//  action: "剪刀石頭石頭",
//  attack: () => {
//        window.runnerWindow.proxyConsole.log(`${name}使用絕招${action}`)
//    },
//  name: "小傑"
// }
console.log(h.action)
//  "剪刀石頭石頭"
```

### 產生空物件：
有兩種方法可用。
1. const a = { }
2. const b = Object.create(null)
=> 利用指定的原型(prototype)把東西灌進去。

重要觀念：
1. 所有的物件都有__proto__屬性
使用後可以找到他的原型。
2. 所有的 function 都有 prototype 屬性
預設的 prototype = { }。
.map 方法其實是 prototype 裡面的屬性，後面的值是 function，用來做事。
```=js
//  對 prototype 物件新增 attack 屬性，值是後面的 function
Hero.prototype.attack = function() {
    console.log("attack")
//  
}
```
原型鏈(prototype chain)：連續使用__proto__可以一層一層往上找到原型。

正常來說印出沒有的屬性應該要會得到 Error，但在 JS 會得到 undefined，
而印出沒有的屬性並呼叫會得到 TypeError，因為呼叫 undefined， undefined 不是 function，會出錯。



```=js
//  建構函數，通常會把函數名稱的首字改成大寫 hero => Hero ，方便辨識這是物件不是函數。
//  這邊的 Hero 稱為建構子，函式前面有 new 的都叫建構子。
function Hero(name, action) {
  // new 做的事情
  // 1. 建立一個空物件
  // 2. 把 this -> {}
  // 3. 把 this.__proto__ -> Hero.prototype ( 預設值: { } )
  // 4. 自動 return this  //  不要自己多寫 return，如果是物件會覆蓋掉 this 值
  this.name = name
  this.action = action
}
```
```=js
function hello() {
  console.log("hi")
}

const h = new hello()
console.log(h)
//  hello { } ，裡面的 this = 函式名稱 + 空物件
console.log(this)
//  { } ，外面的 this 空物件
---------------------------
const h = hello()
console.log(h)
//  undefined，沒有 return 值

```

.map的來源：
list.map 一開始會找不到，因為 list 沒有 map 方法可用
=> 往.__proto__找，但因為 new 的關係會自動轉向到.prototype
=> prototype 裡面有 map 方法
=> 最後會找到 list.prototype.map
```=js
const list = [1, 2, 3, 4, 5]  //  左邊跟 list = new Array(1, 2, 3, 4, 5) 是一樣的東西


list.__proto__ === Array.prototype   // true
list.__proto__.map === Array.prototype.map  // true
```

所有的 function 都有回傳值，當沒有寫 return 時會有兩種預設值：
1. 一般的 function 會回傳 undefined
2. 使用 new 建立的 function 會回傳 this 的值 


## class
ES6才有的語法糖衣，本質上還是使用__proto__去做事。
class => new => instance(實體)
(烤盤)   (透過)   (雞蛋糕) 
如果 new Hero() 想帶引數進去，一定要搭配建構子constructor()使用。
constructor 裡面只放屬性，行為請寫在外面。
```=js
class Hero {
    constructor(name) {
        this.name = name
    }
}
let h = new Hero("奇犽")
console.log(h)
```


```=js
class 靈長類 {
  squash() {
    console.log("!!!!");
  }
}
//  黑猩猩是一種靈長類
class 黑猩猩 extends 靈長類 {
}

class 人 extends 靈長類 {
}

me = new 人()
me.squash()

you = new 黑猩猩()
you.squash()
```
---

###### tags: `JavaScript`