JS 建構函式與類

致于数据科学家的小陈發表於2024-04-07

嚴格來說, JS 並不是一個物件導向的語言, 類似 Java, Python, C++ 這樣的. JS 的獨特精妙的設計其實是 原型 prototype 因此這裡講一嘴物件導向其實是為了後面引出原型的東西.

總之, JS 的物件導向 (封裝, 繼承, 多型) 並不真正存在, 但可以巧用 prototype 近似實現而已.

後來看作者自己說之所以搞這麼一通主要也是為了靠近和迎合一下 Java 而已. 但 JavaScript 和 Java 除了名字有點像, 其他哪裡都不像, 完全是兩個領域的東西.

new 呼叫函式 4 步走

在 js 中函式的呼叫大致有好幾種常見的, 如 函式宣告呼叫, 匿名函式呼叫, 物件.方法呼叫, call 和 apply 呼叫. 而這裡將要說的一種呼叫是透過 new 來呼叫函式.

new 函式()

注意這裡的 new 和其他物件導向的語言不太一樣, 並非是 new 一個物件這麼簡單哦, 但這裡呢還是從規則和語法層面先了解再說吧, 它主要會進行 "四步走":

  • 函式體內會自動建立一個空物件 {}
  • 函式的上下文 (this) 會指向這個空物件
  • 函式體內的語句會執行
  • 函式會自動返回上下文 this 不論函式是否有 return
function fn() {
  this.a = 1
  this.b = 2
}

var obj = new fn()
console.log(obj);

這裡就用了 new 來呼叫函式, 咱們就仔細來分析一波這個過程吧.

// 第一步: 建立空物件
var obj = {}

// 第二步: this 指向這個空物件
this = obj

// 第三步: 函式體內的語句執行
obj = { a: 1, b: 2}

// 第四步: 函式自動返回 this
return this

因此上例 new 呼叫函式()程式的執行結果就是返回一個物件, { a: 1, b: 2 }. 這個 new 來呼叫函式會自動返回一個物件, 且會執行一些邏輯就還是有點東西的哦.

建構函式

就是類建立時的一些自動呼叫的方法呀, 初始化啥的, 即 Java 類裡面的同類名一致的方法實現, 或者是 Python 類裡面的 def __ init __ 它的內部語句會給剛建立的物件 (例項化) 新增若干屬性和方法, 助力其完成物件的初始化.

在 JS 中建構函式必須要透過 new 進行呼叫, 開發者們也約定建構函式命名時首字母要大寫.

當然咱不遵守約定就小寫也是行的, 只是有點不講武德而已.

function People(name, age, sex) {
  this.name = name 
  this.age = age 
  this.sex = sex
}

var youge = new People('油哥', 28, '男')
var yaya  = new People('亞亞', 18, '女')

  • 建構函式的關鍵在於 new 關鍵字呼叫, 而非是否函式首字母大小寫
  • 建構函式中的 this 指向例項物件而非函式本身

接著嘗試給物件新增一下方法看看:

function People(name, age, sex) {
  this.name = name 
  this.age = age 
  this.sex = sex

  this.sayHi = function () {
    console.log('我是: ', this.name, '今年: ', this.age, '歲啦!');
  }
}

var youge = new People('油哥', 28, '男')
var yaya  = new People('亞亞', 18, '女')

youge.sayHi()
yaya.sayHi()

PS C:\Users\Administrator\Desktop> node test.js
我是:  油哥 今年:  28 歲啦!
我是:  亞亞 今年:  18 歲啦!

類與例項

上面所談的關於 JS 中透過建構函式便基本實現了物件導向的一些核心要素. 比如在寫建構函式 People 時, 我們用的核心思想是 抽象 . 然後再透過 new 函式() 的四步走時, 建立了新物件, 新增了一些屬性和方法, 則實現了 封裝 和進行例項化.

計算機其實就是對現實世界的抽象. 裡面的類和例項也對應著現實世界中的 "歸類 和 個體".

從程式語言來看呢, Java, C++, Python 是物件導向的 OO 語言, 而 JavaScript 是基於物件 object-based 的語言. JS 中的建構函式可以類比於物件導向裡面的 class . 但二者的實現邏輯是完全不同的. JS 的獨特之處是基於原型 prototype 的設計哦.

當然在 ES6 以後 JS 也引入了一個 class 的關鍵字 和建構函式 constructor 來模擬純面嚮物件語言的特性, 如繼承. 但本質上還是基於原型鏈來展開的.

關於建構函式和類的簡單認知就差不多了, 核心還是為了引出 JS 原型 這個有點牛的東西.

相關文章