---
# System prepended metadata

title: 0626 JavaScript
tags: [JavaScript]

---

**Outline**
* 邏輯短路
* OOP 物件導向程式設計
* prototype chain 原型鏈
* prototype 原型
* class 類別
* extends 繼承
* 閉包 closure


**Tip**
```
&& -> 而且
|| -> 或者
Object.create( X ) -> 以 X 為原型來產出物件
```

**邏輯短路**
```js
function isAdult(age) {
  return age > 18
}

function vote() {
  // 較花時間的
  for(let i = 0; i < 1000000000; i++) { }
  console.log("vote!")
  return true
}

isAdult(20) && vote()

if (isAdult(20)) {
  vote()
}
// 短路 short 
```

**OOP 物件導向程式設計**

物件 => 屬性 + 行為

類別 class

實體 instance

實體 = 類別.new

e.g.
you = human.new
me = human.new

class 可以定義一些共通的方法 ( method ) 放在裡面

JavaScript 裡面並無class的概念
但可以藉由 Object.create() 來達到類似 OOP 的效果

e.g.
```js
const actions = {
    attack: function () {
        console.log("go")
    },
    eat: function () {
        console.log("yummy")
    }
}

function heroCreator(name, power) {

// 用 Object.create() 這個方法並以 actions 來當作原型產出
    const hero = Object.create(actions)
    hero.name = name
    hero.power = power
  
    return hero
}
  
const hero1 = heroCreator("cc", 100)
const hero2 = heroCreator("ff", 200)

console.log(hero1, hero2)
// 這邊會得出
// hero1{ name:cc, power:100 }
// hero2{ name:ff, power:200 }

hero1.attack()
hero2.eat()
// 雖然在hero1與hero2的物件中沒有 attack() 跟 eat()，
// 但因為用了 Object.create(actions) 來產出，所以可以執行，達到類似 OOP 的效果

```

**prototype chain 原型鏈**

每個物件皆有一個__proto__連接到一個物件
e.g.
Javascript 中，陣列其實也是一個物件
const a = [1, 2, 3] = { 0:1, 1:2, 2:3 }

```js
obj.__proto__
```

**prototype 原型**

每個 function 皆有一個 prototype
prototype 為一個物件 {}

e.g. 
平常使用的 const a = [1,2,3] 其實就 = new Array() 使用 Array 這個函數去 new
一個新的陣列出來，而此時會把 new 出來的物件的 __proto__ 指向 Array 的 prototype

Array.prototype 裡面則放置了很多 Array 能使用的方法 (function)，譬如 map
所以才能使用 a.map

**class 類別**

在 javascript 中，class 只是 function 的語法糖衣
```js
class human{
    constructor(name,age){
    this.name = name
    this.age = age
    }
}
const humanOne = new human(Leo,36)

// 會印出 function
console.log(typeOf(human))
```

**extends 繼承**

```js
class o {
    constructor(){
    }
    grab(){  
    }
}

class human extends O {
    constructor(){
    }
}

const Leo = new human()
Leo.grab()
// 因為用 extends 繼承自 O 這個 class，所以 Leo.grab() 可行
```

**閉包 closure**

底下的兩組迴圈會印出不同的答案是因為當使用 var 宣告 i
i 在迴圈跑完後還會存在 ( 不過變為 3 )，所以會印出 3 3 3

而當用 let 宣告 i，因為 javaScript 判斷 i 在迴圈跑完後會不存在
於是先行把 i 值給了 console.log(i) 再讓他去 web API 排隊

```js
for ( var i=0; i<3; i++ ){
setTimeout(()=> console.log(i),1)
}
// 會印出 3 3 3

for ( let i=0; i<3; i++ ){
setTimeout(()=> console.log(i),1)
}
// 會印出 0 1 2
```
