iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
自我挑戰組

JavaScript101與人生幹話系列 第 28

JavaScript101與人生幹話- 繼承與原型鍊

  • 分享至 

  • xImage
  •  

繼承與原型鍊

1-1原型鍊的概念 - 為什麼有原型

原型,可以當作同一類別的物件具有共同的函式,或是屬性。
舉個例子例如狗,會叫,會挖土,今天要創造一隻臘腸狗,也會包含狗會叫,會挖土的特性。
例如以下範例:使用建構式自定義原型

// 建構式'狗'
// 建構屬性
function Dog(type, name, leg, body, color){
    this.type = type,
    this.name = name    
    this.leg = leg,
    this.body = body,
    this.color = color            
}
// 建立函式
Dog.prototype.bark = function(){
    console.log(this.name + 'bark')
}
Dog.prototype.dig = function(){
    console.log(this.name + 'dig')
}
// 建立一之名子叫東東的臘腸狗
const dondon = new Dog('臘腸', '東東', '短', '長',  '黑')
console.log(dondon)
dondon.bark()
dondon.dig()

JS原型 簡單範例

1-2原型

在JS中不像其它語言有類別,原型基本上都是物件。
物件與又可以繼承下去型成繼承練。如下圖

圖片來源;六角學院JS核心篇
實體物件使用.來查找方法,如果找不到則會向上層查找。如下圖

圖片來源;六角學院JS核心篇
由同一個原型所產生的不同物件實體也會繼承同個原型的方法。


圖片來源;六角學院JS核心篇

1-3新增原型的方法

範例如下

// 使用原型.prototype增加功能,範例如下
Array.prototype.showLast = function (){
  return this[this.length - 1]
}

const arr = [1, 2, 3]
// 因為arr是陣列所以可以使用Array的方法
console.log(arr.showLast()) // 3

// 使用原型.prototype增加Object的方法
// 不用箭頭函式是因為箭頭函式的this指向比較特別,他會指向所在地的物件,而不是呼叫他的物件。
Object.prototype.getName = function (){
  return this.name
}

const personData = {
  name: 'Jack',
  age: 28,
  location: 'Taichun'
}
// 使用新增的物件方法
console.log(personData.getName()) // "Jack"
arr.name = "I'm array"
// 陣列本身也式物件所以也可以使用新增的物件方法
console.log(arr.getName()) // "I'm array"

JS 新增原型的方法範例

1-4 原始型別的包裹物件與原型的關聯

新增原型的方法,原始型別因為包裹物件的關係也可以使用新增的方法
範例如下:

// 新增平方功能
Number.prototype.square = function (){
    return this * this
}
const num = 6
console.log(num.square()) // 36
// 新增一個顯示最後一個字的功能
String.prototype.lastText = function (){
    return this[this.length - 1]
}
const string = 'Jack'
console.log(string.lastText()) // k

// 新增一個顯示現在時間的功能
Date.prototype.showDate= function (){
    const yyyy = String(this.getFullYear())
    const mm = String(this.getMonth() + 1)
    const dd = String(this.getDate())
    const date =yyyy + '/' + mm + '/' + dd
    return date
}
const date = new Date()
console.log(date.showDate()) // 2022/7/4

1-5 使用 Object.create 建立多層繼承

1-5-1 Object.create可以把物件當作原型使用。

範例如下

const dondon = {
    name:'東東',
    type:'臘腸',
    leg:'短',
    body:'長',
    color:'黑色'
}
const white = Object.create(dondon)
white.name = '小白'
white.color = '白色'
console.log(white) // 如下圖


可以發現在屬性prototype中找到東東的資料
另外console.log(white.type) // 臘腸

1-5-2 製做自己的原型練

以下範例使用Object.create製作原型練。
動物界=>狗=>各別的狗

// 動物件的建構式
 function Animal(type) {
    this.animal = 'animal'
    this.type = type
  }
  // 加入動物界的方法
  Animal.prototype.move = function () {
    return this.name + '移動了'
  }
  Animal.prototype.eat = function () {
    return this.name + '吃東西'
  }

  // 狗的建構式
  function Dog(name, type, kind, color, body, leg) {
    // 利用call把Animal的constructor帶入
    Animal.call(this, type)
    this.name = name,
      this.kind = kind,
      this.color = color,
      this.body = body,
      this.leg = leg
  }
  // 加入狗的方法

  // 使用Dog.prototype繼承Animal.prototype
  Dog.prototype = Object.create(Animal.prototype)
  // 補上Dog的constructor,不然只會繼承animal的constructor
  // 為了確保原型完整性方便以後好查,不用補也會正常運作
  Dog.prototype.constructor = Dog

  Dog.prototype.bark = function () {
    return this.name + '吼叫'
  }
  Dog.prototype.dig = function () {
    return this.name + '挖洞'
  }
  // 創造一隻叫東東的狗
  const dondon = new Dog('東東', '犬', '臘腸', '黑', '長', '短')
  console.log(dondon)
  console.log(dondon.constructor)
  console.log(dondon.move())
  console.log(dondon.eat())
  console.log(dondon.bark())
  console.log(dondon.dig())

  // 貓的建構式
  function Cat(name, type, kind, color, body) {
    // 利用call把Animal內的屬性帶入
    Animal.call(this, type)
    this.name = name,
      this.kind = kind,
      this.color = color,
      this.body = body

  }
  // 加入貓的方法
  Cat.prototype = Object.create(Animal.prototype)
  Cat.prototype.constructor = Cat
  Cat.prototype.meow = function () {
    return this.name + '喵叫'
  }
  Cat.prototype.jump = function () {
    return this.name + '從高處跳落'
  }
  const mimi = new Cat('咪咪', '貓', '短毛貓', '橘色', '胖')
  console.log(mimi)
  console.log(mimi.move()) // 咪咪移動了
  console.log(mimi.eat()) // 咪咪吃東西
  console.log(mimi.meow()) // 咪咪喵叫
  console.log(mimi.jump()) // 咪咪從高處跳落

下圖是有利用call帶入Animal的ocnstructor

下圖是沒有利用call帶入Animal的ocnstructor

可以比較出來domdom少了animal與type的屬性。

1-5-3 製作自己的原型練-2

// 生命建構式
function Life (){
  this.isLife = true,
  this.status = 'Living'  
}
// 生命的方法
Life.prototype.breath = function(){
  return this.name + '呼吸'
}
// 動物建構式
function Animal(){
  Life.call(this)
  this.type = 'animal'
}
Animal.prototype = Object.create(Life.prototype)
Animal.prototype.constructor = Animal
// 動物的方法
Animal.prototype.eat = function(){
  return this.name + '吃東西'
}
// 狗
function Dog(species, color, size, name){
  Animal.call(this)
  this.species = species,
  this.color = color,
  this.size  = size,
  this.name = name  
}
// 狗的方法
Dog.prototype = Object.create(Animal.prototype)
Dog.prototype.constructor = Dog
Dog.prototype.bark = function () {
  return this.name + '吼叫'
}
// 狗實體
const dondon = new Dog('犬', '黑', '小', '東東')
console.log(dondon)
console.log(dondon.breath())
console.log(dondon.eat())
console.log(dondon.bark())

// 貓建構式
function Cat (species, color, name) {
  Animal.call(this)
  this.species = species,
  this.color = color,
  this.name = name 
}
// 貓的方法
Cat.prototype = Object.create(Animal.prototype)
Cat.prototype.constructor = Cat
Cat.prototype.meow = function(){
  return this.name + '喵叫'
}
//實體貓
const nini = new Cat('貓', '橘','妮妮')
console.log(nini)
console.log(nini.breath())
console.log(nini.eat())
console.log(nini.meow())

// 植物建構式
function Plant(){
  Life.call(this)
  this.type = 'plant'
}
Plant.prototype = Object.create(Life.prototype)
Plant.prototype.constructor = Plant
// 植物的方法
Plant.prototype.photosynthese = function(){
  return this.name + '進行光合作用'
}

// 薄荷建構式
function Mint (species, color, kind, name) {
  Plant.call(this)
  this.species = species,
  this.color = color,
  this.kind = kind,
  this.name = name 
}
// 薄荷的方法
Mint.prototype = Object.create(Plant.prototype)
Mint.prototype.constructor = Mint
Mint.prototype.mintSmill = function (){
  return this.name + '散發薄荷香味'
}
// 薄荷實體
const myMint = new Mint('薄荷', '綠色','草本','我的薄荷')
console.log(myMint)
console.log(myMint.breath())
console.log(myMint.photosynthese())
console.log(myMint.mintSmill())

// 芒果建構式
function Mongo(species, kind, name, isFurit){
  Plant.call(this)
  this.species = species,
  this.kind = kind,
  this.name = name,
  this.isFurit = isFurit  
}
// 芒果的方法
Mongo.prototype = Object.create(Plant.prototype)
Mongo.prototype.constructor = Mongo
Mongo.prototype.furit = function(){
  return this.name + '結出果實'
}
// 芒果樹實體
const myMongo = new Mongo('芒果', '木本', '我的芒果樹', true)
console.log(myMongo)
console.log(myMongo.breath())
console.log(myMongo.photosynthese())
console.log(myMongo.furit())

人生幹話 - 爛地方是留不住人才的

因為我們對法規比較了解,所以主管安排我們兩個接手原本是主管的工作公司的法規教育訓練,美其名曰給你磨練的機會,但實際上只是公司想要省講師費,主講人是我那位新同事,不過就在成為內部講師的前兩個月他就離職拉,這麼優秀的人怎麼可能會在這種奇怪的公司久待呢?這個屎缺又落到我的上頭啦,你說每個月領不到3萬又要風險管理,又要當講師、又要協調各部門,不誇張嗎?不意外的老闆又發作了,又對外喊說2020年底新產品能上市,因為新同事離職他的工作自然就由我接手,所以又要努力生文件了,那上課的事情自然也是延後了。


上一篇
JavaScript101與人生幹話-運算子、型別與文法
下一篇
JavaScript101與人生幹話 - 屬性的特徵與Getter/Setter
系列文
JavaScript101與人生幹話30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言