---
# System prepended metadata

title: '**==小小筆記篇==**'

---

# **==小小筆記篇==**

#### 原始型別
##### !! 注意 原始型別 中並沒有陣列，陣列的原型也是由物件組成
![](https://i.imgur.com/Yhs8h3g.png)

##### 平常在使用的map、for of，join、push等等都是存在於proto裡面的方法(功能)，原型會往上找，如
![](https://i.imgur.com/WzrtxoF.png)


##### 陣列原型中並沒有.hasOwnProperty，但陣列卻可以使用


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

```javascript=
0: 1,
1: 2, // 包含1 true
2: 3
```
#### 事件委派

##### 透過事件冒泡的原理進行事件委派，把點擊事件寫在，上一層的menu，再進行分類處理
其實不一定要用data- 來當標籤，用ID或class也可以，他也的抓到，就連他上一層也都抓的到(畢竟點擊事件寫在上一層)，不過這種資料傳遞的事，就交給data-吧
```javascript=
  <div id = "menu">
    <button data-key="add">add</button>
    <button data-key="update">update</button>
    <button data-key="remove">remove</button>
  </div>
    <script>
      let menu = document.querySelector('#menu')
      menu.addEventListener('click', function(e){
        let key = e.target.getAttribute('data-key')
				// console.log(key)
        if (key === 'add') console.log('add') // add
        if (key === 'update') console.log('update') // update
        if (key === 'remove') console.log('remove') // remove
      })
    </script>
```

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

#### ... 可以用在類陣列轉陣列，或是不固定長度的參數
```javascript=
    function number(num) {
      console.log([...arguments]) // ["1", "2", "3"]
    }
    number(1, 2, 3)
```
##### 用set特性過濾掉重複的值
```javascript=
    let arr = ['A', 'B', 'C', 'A', 'D', 'E', 'D', 'F', 'G']
    let result = [...(new Set(arr))]
    console.log(result) // ["A", "B", "C", "D", "E", "F", "G"]
```
##### 不固定長度的參數
```javascript=
    function number(...num) {
      console.log(num) // ["1", "2", "3"]
    }
    number(1, 2, 3)
```
#### 箭頭函式 ####
```javascript=
    let Hello = Hello => console.log(Hello) // Hello
    Hello('Hello')
    // 單行不用寫 {}
    // 只有一個參數情況下 可以不寫 ()
```
```javascript=
    let sum = (a, b) => a + b // 箭頭函式自帶return
    let total = sum(5, 6)
    console.log(total) // 11
```
```javascript=
// 在ES6中參數可以給預設值
    let sum = (a = 5, b = 6) => a + b // 箭頭函式自帶return
    let total = sum() // 若()有參數設定 以()內為主
    console.log(total) // 11
```
```javascript=
    let sum = (a, b) => a + b // 箭頭函式自帶return
    let total = sum()
    console.log(total || 100) // 100 // 若出現 NaN undefined等等 會出現 100
```
#### 提升(Hoisting) ####
#### 變數提升，在javascript 裡面var有個特性就是會提升，let不會，這種特性使得找錯更困難

```javascript=
  (function(){
    console.log(name) // undefined
    var name = 'Lee'
  }())
```

##### 這一段會等於宣告的部分被提升了

```javascript=
  (function(){
		var name
    console.log(name) // undefined
    name = 'Lee'
  }())
```


##### let 則不會
```javascript=
  (function(){
    console.log(name) 
     // ReferenceError: Cannot access 'name' before initialization
    let name = 'Lee'
  }())
```

#### 函式提升，函式也會提升

```javascript=
    console.log(func()) // Hi
    function func() {
        return 'Hi'
    }
```
#### 像這種 表達式，或是箭頭函式就不會
```javascript=
    console.log(func())
    // ReferenceError: Cannot access 'func' before initialization
    let func = () => {
        return 'Hi'
    }
```

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

#### 遞迴(函式自己呼叫自己稱之為遞迴)

```javascript=
function reciprocal(n) {
    if (n === 0) {
        return 'end'; // 出口
    }
    console.log(n) // 依序顯示 10 to 1 最後是end
    return reciprocal(n - 1);
}
console.log(reciprocal(10))
```
以數學的階乘為例

```javascript=
function factorial(n) {
    if (n === 0) {
        return 1; // 出口
    }
    return n * factorial(n - 1);
}
console.log(factorial(4)) // 4*3*2*1
```

#### 閉包(Closure) ####
```javascript=
// 變數的作用域開始於函式 終止於函式結束
function makeFunc() {
    let a = 5;
        function displayName() {    
            let b = 5
            return a + b // 無須參數 變數作用域會往下流
        }
    return displayName;
    }
  let myFunc = makeFunc();
  console.log(myFunc()) // 10 
	console.log(a) // a is not defined
```

```javascript=
    let val = 'apple'
    function bar() {
        let val = 'banana'
        foo()
    }
    function foo() {
        console.log(val)
    }
    bar() // 結果是apple 因為在不同作用域中 要變成 'banana' 要帶入參數 val
```

#### this的應用 (非物件調用通常指向window，在物件上的調用指向物件的上一層)
#### !!! 箭頭函式用this很雷，就算是在物件也是指向window，如都沒有not de find
```javascript=
	var val = 'apple'
	function bar() {
			let val = 'banana'
		    return function () {
			   return this.val
			}
	}
	let result = bar()
	console.log(result()) // apple 改成 val就變banana
```
##### 漂亮阿姨的小孩

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


#### 原型鍊 與 建構式
##### 複製物件會出現的問題 物件有參照址(記憶體有關來著) 複製過來的物件改變值會把原本的物件也改變

##### 就算是一模一樣的物件也是 false == 也是 false
![](https://i.imgur.com/9kEJYhX.png)

##### 必須是複製過來的物件才會是true 但更改複製過來的物件也會去動到原本的物件
![](https://i.imgur.com/Yhm2R1g.png)
##### 陣列的原始型別也是物件，直接比對也會是 false
![](https://i.imgur.com/edElIaZ.png)


##### 如下
```javascript=
    let Lee = {
      name: 'david',
      sex: 'male',
      kind: true
    }
    let Ji = Lee
    Ji.name = 'momo'
    console.log(Lee.name) // momo
```
##### 試試Object.create // 他會製造空物件，但其原型會繼承()內的物件

```javascript=
    let Lee = {
        name: 'david',
        sex: 'male',
        kind: true
    }
      let Ji = Object.create(Lee)
      console.log(Ji)
      console.log(Ji.name)
      console.log(Ji.sex)
```
##### ㄟ !? 空物件卻可以使用
![](https://i.imgur.com/c8EIXp3.png)

##### 讓我們往下看
##### ㄡ～原來是他往上找，找到可以用的屬性

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


##### 更動看看
```javascript=
    let Lee = {
        name: 'david',
        sex: 'male',
        kind: true
    }
      let Ji = Object.create(Lee)
      Ji.name = 'momo'
      console.log(Ji)
      console.log(Ji.name)
      console.log(Ji.sex)

```
##### 這時候不會影響到原物件
##### ==雖然沒有sex這個屬性，但他會往上找上一層原型裡就sex這個屬性(繼承自Lee)，往上一層找原型裡面的方法是很重要的特性==

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

##### 建構式
```javascript=
    function people (name, sex) {
      this.name = name
      this.sex = sex
      this.kind = true
    } // 這相當於設計圖
		
      let Lee = new people('david', 'male') // 根據需求製造出來
      let Ji = new people('momo', 'Female')
			
     people.prototype.ChildBirth = function() {
      if(this.sex === 'Female') {
        console.log(`${this.name} is ${this.sex} ${'可以懷孕'}`)
        } else {
          console.log(`${this.name} is ${this.sex} ${'不能懷孕'}`)
        }
      } // 相當於再加點新設計
        console.log(Lee.name) // david
        console.log(Lee.ChildBirth()) // david is male 不能懷孕
```
##### class寫法(ES6語法糖) 跟上面的設計圖(function people)一樣的意思
##### class 只是宣告函式的一種特別的語法 javascript 並沒有真正的「類別」實體。
```javascript=
    class people {
      constructor(name, sex) {
       this.name = name
       this.sex = sex
       this.kind = true
      }
    }

```
#### 繼承 (extends) 又稱擴充 (用ES6語法糖class)

```javascript=
     class people {
         constructor(name, sex) {
             this.name = name
             this.sex = sex
             this.kind = true
       }
				 
       sayHello() { // 宣告方法 (Method)
         return `Hello ${this.name}`;    
       }
			
    }
        people.prototype.ChildBirth = function() {
        if(this.sex === 'Female') {
            console.log(`${this.name} is ${this.sex} ${'可以懷孕'}`)
            } else {
            console.log(`${this.name} is ${this.sex} ${'不能懷孕'}`)
            }
        } // 相當於再加點新設計
        // people2 繼承 people 可以改寫或新增新設定
        class people2 extends people {
        constructor(name, sex, other) {
            super();
            this.name = name
            this.sex = sex
            this.other = other
            this.kind = false
        }
    }
        let bo = new  people2('bobo', 'Female', 'what?')	
            
        console.log(bo.other) // what?
        console.log(bo.ChildBirth()) // bobo is Female 可以懷孕
        console.log(bo.sayHello()) // Hello bobo
        console.log(bo.kind) // false

```

##### Object.create繼承法
```javascript=
    // - 父類別
    function people() {
      this.name = ''
      this.sex = ''
      this.kind = true
    }
      // 父類別的方法
      people.prototype.ChildBirth = function(name, sex) {
      this.name = name
      this.sex = sex
      if(this.sex === 'Female') {
              console.log(`${this.name} is ${this.sex} ${'可以懷孕'}`)
          } else {
              console.log(`${this.name} is ${this.sex} ${'不能懷孕'}`)
           }
      };

      // 子類別
       function Lee() {
         people.call(this); // call super constructor.
      }

       // 子類別擴展(extends)父類別
      Lee.prototype = Object.create(people.prototype);
      Lee.prototype.constructor = Lee;

      let rect = new Lee();

      rect.ChildBirth('david', 'male'); // david is male 不能懷孕
```
#### 電話產生器 ####
```javascript=
  function nuuber () {
    let arr = []
    function nuuber2 () {
     for(let i = 0; i <= 9; i++) {
     arr.push(i)
     for (let i = 0; i < (Math.floor(Math.random() * 2)); i++){
     arr.reverse()
        }
     }
     arr = arr.join('').slice(2, 10)
       return arr
    }
      return nuuber2()
  }
    let Num = nuuber()
    console.log(`09${Num}`)
```

```javascript=
  function nuuber () {
    let arr = []
    function nuuber2(){
    for(let i = 1; i <= 8; i++) {
      arr.push(Math.floor(Math.random() * 9))
      arr.reverse()
       }
       arr = arr.join('')
       return arr
     }
      return nuuber2()
    }
    let Num = nuuber()
    console.log(`09${Num}`)
```
#### 數字轉字串 ####
```javascript=
    let num = 1
    let numtoStr = num + '' 
    //除了toString 還可以 加上一個空字串
    console.log(typeof numtoStr) // string
```
#### 字串轉數字 ####
```javascript=
    let str = '1'
    let strtoNum = +str // or str - 0
    //除了 parseInt Number 還可以 + / -0
    console.log(typeof strtoNum) // number
```