# ES5 Function Constructors and ES6 Classes ## Prototype(原型), Prototype Inheritance(原型繼承)  <br >  <br > ## Building Object 建立物件 > ### ES5 Function Constructors 函式建構式 和 ES6 Classes 類別 > ### 都是用來建立物件的方式 ### ES5 Function Constructors 函式建構式 > #### A normal function that is used to construct objects :::success **特點** - function 名稱首字大寫 (covention,小寫不會有任何報錯) - 不 return 任何值 ::: ```javascript= function Person (){ this.firstName = 'John'; this.lastName = 'Doe'; } var john = new Person(); console.log(john); ``` <img src="https://i.imgur.com/5WrnYOY.png" width="500px"> <br > ### 進一步來看`new` 讓這個過程發生了什麼? - 當我們使用 `new` 這個關鍵字時,實際上會先有一個**空的物件**被建立。 - 接著 Person 這個函式會被執行(invoke)。我們知道當函式執行的時候,在 execution context 中會有 `this` 被建立,**而當我們使用 `new` 的時候,函式裡面的 `this` 會被指定成剛剛所建立的那個空物件。** - 所以當執行 Person 這個 `function`,執行到 `this.firstName` 和 `this.lastName` 時,因為 `this` 現在指稱的是那個空物件,所以實際上是在幫這個空物件賦予屬性名稱和屬性值。 - **在這樣的過程中,只要這個函式建構式 Person 沒有指定 `return` 為其他物件,它就會直接回傳給我們這個新建立的物件。** <br > :::warning 函式的最後若 `return` 其他物件,則原新物件內容會被覆蓋 ::: ```javascript= function Person (){ this.firstName = 'John'; this.lastName = 'Doe'; return {"RETURN":"原本this的內容就不會被回傳"}; } var john = new Person(); console.log(john); ``` 回傳的結果如下,原本被建立的新物件不會被回傳,而是回傳我們最後`return`給它的內容: <img src="https://i.imgur.com/3rFKBlu.png" width="500px"> <br> ### 透過 function constructor 函式建構式與 Prototype 的實用處 *透過這樣的方法,我們可以讓所有根據這個函式建構式(function constructor)所建立的物件都包含有某些我們想要使用的方法。如果我們有 1000 個物件是根據這個函式建構式所建立,那麼我們只需要使用 .prototype 這樣的方法,就可以讓這 1000 個物件都可以使用到我們想要執行的某個 method* 如此,我們就可以透過同一個函式建構式建立出很多不同的物件: <img src="https://i.imgur.com/FJtYv1k.png" width="500px"> <br> ```javascript= function Person(firstName, lastName){ this.firstName = firstName; this.lastName = lastName; } Person.prototype.getFullName = function(){ return this.firstName + ' ' + this.lastName; } var john = new Person('John', 'Doe'); console.log(john.getFullName()); // John Doe var jane = new Person('Jane', 'Doe'); console.log(jane.getFullName()); // Jane Doe ``` <br > :::danger ❗️ 我們不該把 methods (方法) 放在 function constructor 中。 ::: - 如果我們是把這個方法直接寫在函式建構式中,那麼每一個物件都會包含有這個方法,如果我們有 1000 個物件根據這個函式建構式所建立,那麼這 1000 個物件都會包含這個方法在內,如此將會占據相當多的記憶體;但如果是建立在 prototype 中,我們只會有一個這樣的方法。 - 所以,為了效能上的考量,通常會把方法(method)放在建構式的 prototype 中,因為它們可以是通用的;把屬性(property)放在建構式當中,因為每一個物件可能都會有不同的屬性內容,如此將能有效減少記憶體的問題。 <br > **** ### ES6 Classes 類別 >#### 在 JavaScript 中仍然是使用 **prototypal inheritance** 的方法。 `class` 的這種做法在 JavaScript 實際上只是 syntax sugar(語法糖),**它只是用來建立物件和原型的另一種撰寫方式**,但背後運作的邏輯其實和 function constructor 或者是 `Object.create` 還是一樣的。 ```javascript= class Person{ constructor(firstname, lastname){ this.firstname = firstname; this.lastname = lastname; } getFullName(){ return "Hello "+ this.firstname + " " + this.lastname; } } var john = new Person("John","Doe"); console.log(john.getFullName()); // John Doe var jane = new Person('Jane', 'Doe'); console.log(jane.getFullName()); // Jane Doe ``` - `class` 中,我們可以使用 `constructor` 來建立物件,同時,我們也可以在 `class` 中放入方法,最後一樣透過 `new` 這個關鍵字,我們就可以建立john這個物件。要注意的是,**在一個`class`中,只能有一個 `constructor`**。 - 在 JavaScript 中雖然和其他程式一樣使用了 `class` 這個關鍵字,但要注意的是 **`class` 裡面所建立的內容仍然是個物件**。 上面 `class` 所建立的物件,與下方 function constructor 物件相同 :point_down: ```javascript= function Person(firstName, lastName){ this.firstName = firstName; this.lastName = lastName; } Person.prototype.getFullName = function(){ return this.firstName + ' ' + this.lastName; } var john = new Person('John', 'Doe'); console.log(john.getFullName()); // John Doe var jane = new Person('Jane', 'Doe'); console.log(jane.getFullName()); // Jane Doe ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up