# 各式各樣學習分支 ###### tags: `學習筆記` `物件導向` ## 建構函數 & Class 的區別 參考來源 : >[ ES6 中最容易誤會的語法糖 Class - 基本用法](https://medium.com/enjoy-life-enjoy-coding/javascript-es6-%E4%B8%AD%E6%9C%80%E5%AE%B9%E6%98%93%E8%AA%A4%E6%9C%83%E7%9A%84%E8%AA%9E%E6%B3%95%E7%B3%96-class-%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95-23e4a4a5e8ed) [物件導向 JavaScript (object-oriented JavaScript)](https://pjchender.dev/javascript/js-oo/) [繼承與原型鍊 - 使用 Object.create 建立多層繼承](https://israynotarray.com/javascript/20210221/2645303265/) [關於 Object ,一口氣全說完](https://medium.com/enjoy-life-enjoy-coding/javascript-%E9%97%9C%E6%96%BC-object-%E4%B8%80%E5%8F%A3%E6%B0%A3%E5%85%A8%E8%AA%AA%E5%AE%8C-4bb924bcc79f) >JavaScript使用 **建構式函式(constructor function)** 來定義物件和他們的特色, >例如: function Person() {}; >用開頭大寫來區分是一般函式還是**建構式函式(constructor function)**,沒辦法很清楚的分辨 >現在直接用 **ES6 語法糖 class** 搭配 constructor () {}; 就能清楚的分辨。 >可以看做是 function Person() {} = constructor () {}; - constructor 擁有 prototype 屬性。 - class 沒有 hoisting 的機制。 ```javascript= Class Person { constructor(name) { this.name = name; } // 這個 getInfo 會直接變成 Person 的 prototype (原型) getInfo() { const state = 'Taiwan'; return `${this.name} is from ${this.state}`; } } ``` ### **class 的繼承 extends** 參考資料來源 : > [JavaScript ES6 class 關鍵字](https://www.fooish.com/javascript/ES6/class.html) - 繼承時如果有 consturctor 要用,必須調用 super() 否則會出錯。 - 繼承時如果有 consturctor ,必須調用 super() 後才能引用 this 否則也會出錯。 - 當作物件 super 也可在一般方法中使用,用來引用父類別的方法和屬性 > 這是因為在 ES6 中,是先建立父類別 (parent class) 的物件實例 this 所以必須先執行 super(),然後再用子類別的 constructor 修改 this。 > 透過 super 調用父類別的方法時,super 會綁定子類別的 this > (**原先父類別方法裡面用到 this 的會指向子類別**) ```javascript= class Car { constructor() { console.log('Creating a new car'); } } class Porsche extends Car { constructor() { super(); // 這個 super 就是調用 Car 的建構函數(constructor) console.log('Creating Porsche'); } } let c = new Porsche(); // 依序顯示 // Creating a new car // Creating Porsche ``` - super 關鍵字有兩種用法: 1. 當作函數 super(),只能在子類別的 constructor 中使用,在其他地方用會報錯 2. 當作物件 super,在一般方法中使用,用來引用父類別的方法和屬性 > 第二種用法,透過 super 調用父類別的方法時,super 會綁定子類別的 this (而不是父類別的 this) --- ## 使用 **new** 建立實例步驟 ==可以再多看看其他人怎麼寫== 參考資料來源 : > [JS 的 new 做了哪些事情呢?](https://juejin.cn/post/6968856664560648199) ```javascript= function Person(name,age) { this.userName = name; this.userAge = age; } var personl = new Person('LULU',20) ``` 1. 創建一個空對象。 ```javascript= let obj = {}; ``` 2. 設置原型鏈。 ```javascript= obj.__proto__ = Object.create(Person.prototype); ``` 3. 將建構函式的 this 指向新對象 obj 並執行函數代碼。 ```javascript= let result = Person.apply(obj, arguments); ``` 4. 如果建構函式 return 一個 object 類型,那麼返回此變量,否則返回空對象 ```javascript= typeof(result) === 'object' ? result : obj; ``` --- # **call() & apply() & bind()** 參考來源 : >[call,apply,bind, function currying (科里化), function borrowing (函式借用)](https://medium.com/itsems-frontend/javascript-bind-call-apply-and-function-borrowing-and-currying-6bed787cd3eb) ### **call() & apply() 差別在於第二個參數以後** - 第一個參數 : 指定 **this** 對象 - 第二個以後的參數 : call 為==一個一個==參數帶入 ,apply 為參數==陣列==帶入 - 直接執行函式 ### **bind()** 綁定 this 對象後回傳新的函式 - 第一個參數 : 指定 **this** 對象 - 第二個以後的參數 : 看要不要指定參數值,可給可不給 - 不會執行函式,回傳新的函式 ==科里化== 「**將接收 n 個參數的函式拆解為一連串 n 個只接受一個參數的函式**」 科里化使用 .bind(this) ,用 this 指向自己這個函數,相當於閉包作用, this 後面的參數看是否要指定數值 ```javascript= function add(a, b) { return a + b; } const add10 = add.bind(this, 10); // 這時候 add10 相當於 function add10(b) { // this 後的參數指定 a = 10; const a = 10; // return 用 this 指向自己的 add 函式(閉包的功用) return function add(a, b); } add10(5); // 15 add10(7, 4) // 17 後面的參數 4 就沒有帶進去函式裡面使用了 ``` --- ## **this** 參考資料來源 : >[JavaScript this 的用法](https://shubo.io/javascript-this/) this 的值,是在被呼叫的當下才會決定的。 this 就是當時呼叫這個方法的物件。 沒有物件的時候 this 的值會是 **window**,或是 strict mode 底下的 **undefined**。 **Arrow function (箭頭函式)** 的 this,沒有自己的 this, 他的 this 會等於被宣告當下所在環境的 this。 **結論 : this 就是呼叫方法時,「點」前面的那個物件。 而箭頭函式沒有自己的 this, 他的 this 由外層的環境決定。** > 沒有物件時使用 this 如果是在瀏覽器環境下相當於在 window 物件下使用 this,所以 this 的值當然就是 window。 > 瀏覽器中可以用 "use strict"; 的語法開啟嚴謹模式,可以讓一些不良的寫法拋出錯誤。