# **==小小筆記篇==** #### 原始型別 ##### !! 注意 原始型別 中並沒有陣列,陣列的原型也是由物件組成 ![](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 ```