類別語法並不是要引入新的物件導向繼承模型到 JavaScript 中,而是提供一個更簡潔的語法來建立物件和處理繼承。
(JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.)
ES6 class
// class 像是一個設計圖
class Dog {
setName(name){
this.name = name // 這裡的 this 就是呼叫他的人,操控這個 instance 的人,在這裡就是 d
console.log('this-->',this) // Dog {name: "PooBoo"}
}
sayHello(){
console.log(this.name)
}
}
var d = new Dog() // instance : 用 new 這個關鍵字去實體化
d.setName('PooBoo')
d.sayHello()
var d2 = new Dog()
console.log(d.sayHello() === d2.sayHello()) // true
ES6 class - Constructor
class Dog {
// 在 new 的時候,其實就是在 call 這個 constructor
// 在被 new 時就會 call 這個 function 所以很適合做一些初始化的事情
constructor(name) {
this.name = name
}
}
var d = new Dog('aaa') // new 時帶入參數
ES5 的 class 做了什麼
用一個 function 去實作 constructor
用 prototype 去實作 method
♥♥♥
ES5 裡可以把一個 function 當作一個 constructor 用,new 一個 function 產生一個 instance,背後的機制 javascript 會做好
---> 屬性,method 都放在 constructor
// 這個 function 就是 constructor
function Dog(name) {
this.name = name
this.getName = function() {
return this.name
}
}
var b = new Dog('FooPan')
var d = new Dog('BooPoo')
console.log( b.getName == d.getName)
// false,如果這樣寫 new 幾個 Dog 就會有幾個 getName function
// 因為 function 記憶體位置是不一樣的
// 比較好的寫法是 Dog.prototype.getName
// 使用 prototype 寫法
function Dog(name) {
this.name = name
}
}
// 在 Dog 的 prototype 上加一個 function
Dog.prototype.getName = function(){
return this.name
}
Dog.prototype.sayHello = function(){
console.log(this.name)
}
var b = new Dog('FooPan')
var d = new Dog('BooPoo')
console.log(d) // d 就是 Dog 的 instance
console.log(b.getName === d.getName) // true
// d.__proto__ 是什麼
{getName: ƒ, sayHello: ƒ, constructor: ƒ}
// Dog.prototype(d.__proto__) 有 method and constructor
console.log(d.__proto__ === Dog.prototype) // true
console.log(Dog.__proto__ === Function.prototype) // true
instance 和 prototype 之間是如何串連的
透過屬性 __proto__
在 new 一個 instance 時,javascript 就幫你加了一個屬性 __proto__
soo.__proto__ === Dog.prototype // true
從 prototype 來看「原型鍊」__proto__
instance 身上有 getName (但這樣就會有一直重複複製相同的 function 的問題)
結論:
會先找 instance 裡有沒有 getName()
如果沒有才會去 proto 找
function Dog(name) {
this.name = name
this.getName = function() {
return 'MyName'
}
}
Dog.prototype.getName = function(){
return this.name
}
var soo = new Dog('Soo')
console.log(soo.getName())
// 'MyName'
透過 __proto__這個屬性,可以知道 s.toUpperCase 就是 String.prototype.toUpperCase() 這個 function
var s = 'abcd'
var newS = s.toUpperCase()
s.toUpperCase === String.prototype.toUpperCase //true
s.__proto__ === String.prototype // true
s.__proto__.toUpperCase() === String.prototype.toUpperCase() // true
new 做了什麼事?
產生一個新的 object
執行 constructor,完成物件初始化,有了物件
用 __proto__ 產生關聯
// 產生一個新的 Object
function Dog(name) {
this.name = name
this.getName = function() {
return name
}
}
var soo = new Dog('Soo')
{
name : 'Soo'
getName : function(){ return name }
}
function test() {
console.log(this)
}
test.call(true) // 第一個參數就會是 this
function Dog(name){
this.myName = name
}
Dog.prototype.sayHello = function(){
console.log(this.myName)
}
var booPoo = newDog('booPoo') // newDog 要做 new 做的事情
booPoo.sayHello() // booPoo
// new 在做什麼
function newDog(name){
var obj = {} // 產生一個新的 object
Dog.call(obj, name) // 執行 constructor
console.log(obj) // {myName: "booPoo"}
obj.__proto__ = Dog.prototype // 用 __proto__ 產生關聯
return obj
}
物件導向的基礎
(這是一個箱子裡,有多個你已定義好的功能(你想要的功能),有需要你可以一直複製相同箱子的故事) (在物件導向的世界裡,不太會有直接去 call 一個 function 的情形,例如 add(),通常會是對一個物件做操作,例如:obj.add())
ECMAScript 6 中引入了類別 (class) 作為 JavaScript 現有原型程式(prototype-based)繼承的語法糖。
類別語法並不是要引入新的物件導向繼承模型到 JavaScript 中,而是提供一個更簡潔的語法來建立物件和處理繼承。 (JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.)
ES6 class
ES6 class - Constructor
ES5 的 class 做了什麼
♥♥♥ ES5 裡可以把一個 function 當作一個 constructor 用,new 一個 function 產生一個 instance,背後的機制 javascript 會做好
---> 屬性,method 都放在 constructor
instance 和 prototype 之間是如何串連的
__proto__
__proto__
從 prototype 來看「原型鍊」
__proto__
instance 身上有 getName (但這樣就會有一直重複複製相同的 function 的問題)
結論:
d 的 instance 身上沒有 sayHello,所以往上找 proto
prototype chain 原型練
d.sayHello() 查找順序
d
身上有沒有 sayHellod.__proto__
有沒有 sayHellod.__proto__.__proto__
有沒有 sayHellod.__proto__.__proto__.__proto__
有沒有 sayHello // nullnull
出現代表已經是最上層了string.toUpperCase
透過
__proto__
這個屬性,可以知道 s.toUpperCase 就是 String.prototype.toUpperCase() 這個 functionnew 做了什麼事?
__proto__
產生關聯物件導向的繼承:Inheritance
繼承就像人會遺傳父母的DNA
BlackDog 自己加上 constructor
參考文章
Classes