物件導向


Posted by chihyu on 2021-01-25

物件導向 Object Oriented Programming(中國:面向對象)
不直接呼叫一個 function,而是對某個物件做操作

  • 變成一個模組的感覺(把原本分散的 function 集中起來)
  • 比較有規範
  • 資訊可以被藏起來(封裝,外面不會知道裡面發生甚麼)
    (ex. XHR 發 request 也是使用封裝)
    add() // 直接呼叫一個 function add
    myWallet.add() // 對 myWallet 這個物件呼叫 function add
    
    需要去思考別人該怎麼使用會比較方便

開始使用物件導向

用 class(類別,好比一個設計圖) 去寫一個物件,用 new (好比實體化的東西) 去呼叫 function

  • 出現在 class 裡面的 function 叫做 method
  • new 出來的東西叫做 instance
  • private 的東西不能被外面存取,public 的東西則可以任意更動
  • 使用 getter、setter 可以去決定一些事情(在 function 裡面寫點甚麼來限制甚麼)
    ES6 寫法:
    用 constructor 去設定初始值
    class Dog {
      // setter 去設定甚麼
      constructor(name) { // 建構子 php 用 __construct
          this.name = name
      }
      // getter 去拿取甚麼
      getName() {
          return this.name
      }
      sayHello() {
          console.log(this.name)
      }
    }
    var d = new Dog()
    d.setName('abc')
    d.sayHello() // abc
    

ES5 寫法:

function Dog(name) { // 相當於 ES6 的 constructor
    this.name = name
}
Dog.prototype.getName = function() {
    return this.name
}
Dog.prototype.sayHello = function() {
    console.log(this.name)
}
var d = new Dog('abc')
var b = new Dog('qweqwe')
d.sayHello()

運作機制

d.sayHello()

運作流程:

  1. 看 d 身上有沒有 sayHello,如果沒找到就往上一層找
  2. d.___proto___ 有沒有 sayHello,如果沒找到就再往上一層找
    (d.___proto___ === dog.prototype)
  3. d.___proto___.___proto___ 有沒有 sayHello,如果沒有就在往上一層找
    (d.___proto___.___proto___ === object.prototype)(object 不知道是哪來的)
  4. d.___proto___.___proto___.___proto___ 有沒有 sayHello
  5. 回傳 null,表示找到頂了

prototype chain 原型鏈

  • 共同享有一個 function

繼承

當有共同屬性時,不需要重寫一個,可以用繼承的方式繼承原本寫好的

  • 用 extends 去繼承
    class Dog {
      constructor(name) {
          this.name = name
      }
      sayHello() {
          console.log(this.name)
      }
    }
    class BlackDog extends Dog {
      test() {
          console.log('test!', this.name)
      }
    }
    const d = new BlackDog('hello')
    d.sayHello() // hello
    
    當在繼承裡建立一個 constructor 時,要呼叫 super(),用來呼叫上一層的 constructor,且把參數一起傳上去
class BlackDog extends Dog {
    constructor(name) {
        super(name) // php 是用 parent
        this.sayHello()
    }
    test() {
        console.log('test!', this.name)
    }
}
const d = new BlackDog('hello')
d.sayHello() // hello hello

static

static 的東西不屬於 instance,屬於 class 的
static function 靜態 function
static variable 靜態變數

this

  • 在非物件導向的地方使用 this,this 代表的東西會依據環境而有所不同,瀏覽器的跟 node.js 的 this 不同(瀏覽器-window、node.js-global)
  • this 的值跟他在甚麼時候被定義沒有關係,重點是怎麼去呼叫,判別值的方法可以用 .call() 的方式去看,看.call() 前面的前面接的東西
    'use strict';
    const obj = {
      a: 123, 
      inner: {
          test: function() {
              console.log(this)
          }
      }
    }
    obj.inner.test() // 可以看成 obj.inner.test.call(obj.inner)
    const func = obj.inner.test
    func() // 可以看成 func.call(undefined)
    

嚴格模式 use strict

使用嚴格模式後,在非物件導向的地方使用 this,不管在哪個環境都會是 undefined

'use strict'
function test() {
    console.log(this) // undefined
}
test()

.call()、.apply()

裡面傳的第一個參數可以改變 this 的值,function 的參數寫在第一個參數後面

  • .call():function 的參數用逗號隔開
  • .apply():function 的參數用 array 包起來
'use strict'
function test(a, b, c) {
    console.log(this) // undefined
}
test.call(123, 1, 2, 3)
test.apply(123, [1, 2, 3])

.bind()

綁定 this 的值

'use strict'

const obj = {
    a: 1,
    test: function() {
        console.log(this)
    }
}
const bindTest = obj.test.bind('jkjk')
bindTest.call(123) // jkjk

箭頭函式的 this

跟怎麼去呼叫沒關係,重點是在那裡定義

class Test {
    run() {
        console.log('run this', this)
        setTimeout(() => {
            console.log(this)
        }, 1000)
    }
}
const t = new Test()
t.run() // run 跟 setTimeout 的 this 會一樣

#Web #javascript #Object-oriented







Related Posts

CSS保健室|width、height

CSS保健室|width、height

[重新理解 C++] Array 和 Pointer 的差異

[重新理解 C++] Array 和 Pointer 的差異

程式導師實驗計畫 FE102

程式導師實驗計畫 FE102


Comments