# **==小小筆記篇==**
#### 原始型別
##### !! 注意 原始型別 中並沒有陣列,陣列的原型也是由物件組成

##### 平常在使用的map、for of,join、push等等都是存在於proto裡面的方法(功能),原型會往上找,如

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

```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>
```

#### ... 可以用在類陣列轉陣列,或是不固定長度的參數
```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'
}
```

#### 遞迴(函式自己呼叫自己稱之為遞迴)
```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
```
##### 漂亮阿姨的小孩

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

##### 必須是複製過來的物件才會是true 但更改複製過來的物件也會去動到原本的物件

##### 陣列的原始型別也是物件,直接比對也會是 false

##### 如下
```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)
```
##### ㄟ !? 空物件卻可以使用

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

##### 更動看看
```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),往上一層找原型裡面的方法是很重要的特性==

##### 建構式
```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
```