← Back to list

【JS學習筆記】__proto__ vs. prototype

我是非本科系、正在學前端的新手,想用這裡記錄自己學到的東西。

Kim · 2026-05-21 07:12 · 1 claps · 4.8 min read
#javascript #prototype #constructor #learning
Open on Medium ↗
Wiki topics: UX · UI/UX Design EDU · Education & Learning 🌐 · Web Development

【JS學習筆記】proto vs. prototype

我是非本科系、正在學前端的新手,想用這裡記錄自己學到的東西。

前陣子在學物件導向程式設計的時候,老師有教到 JS 的原型鏈 proto 跟 prototype。一開始在聽 proto 的概念時邏輯還算清晰,但接到 prototype 後思緒整個大混亂,這篇文章是想來整理一下上課教的以及我後來自己上網學的關於 JS 原型鏈。

proto 是每個物件都有的隱藏屬性。

prototype 是每個函式都有的屬性。(預設是一個物件)

proto

[[prototype]] (即 proto

稍後講到 prototype 會提到 [[prototype]],所以這邊想先說明 [[prototype]] 跟 proto 是同個東西但為什麽要分兩個名字。

[[prototype]] 是 ECMAScript 規格書裡的內部欄位名稱,比較像是概念層面的東西,在 JS 程式碼裡是沒有的。

proto 則是我們實作在寫程式碼時會碰到的名稱。

const a = {}

console.log(a.name)  //undefined

a 並沒有 name 這個屬性,所以會印出 undefined。

以初學者也就是我的角度會認為在 console.log(a.name) 時,電腦會去抓 a 然後看到它沒有 name 這個屬性後就回傳 undefined,但實際的操作是找 a 沒有 name,就會繼續往下找 a.proto 有沒有 name,如果沒有會再繼續往下找 a.proto.proto

流程會是這樣:

a.name  // 沒有,往下找
  ↓

a.__proto__.name  // 沒有,繼續往下找
  ↓

a.__proto__.__proto__.name  // 沒有,繼續往下找
  ↓

a.__proto__.__proto__.__proto__  // null,找不到 name 回傳 undefined

prototype

function A() {} 
//函式也是物件所以也會有 __proto__
//而函式的 __proto__ 會指向 Function.prototype

const a = new A()
//new A() 時會建立一個物件,該物件的 __proto__ 會指向 A.prototype

A.__proto__ === Function.prototype   // true
a.__proto__ === A.prototype          // true
function A() {}
//每個函式都會有 prototype

A.prototype
//prototype會被預設為一個物件

prototype 能怎麼運用?

function A() {}

const greeting = {
  sayHi: function(){
  console.log("Hi!!!")
}}

A.prototype = greeting

const a = new A()

a.sayHi()  // Hi!!!

a 本身沒有 sayHi ,上面有說過 new A() 時會建立一個物件,該物件的 proto 會指向 A.prototype ,而 A.prototype 被指定為 greeting ,這樣 new A() 時 sayHi 就可以被共用,所以這時 a.proto 會指向 greeting,a 就有了 sayHi。

大致流程是這樣:

a 本身沒有 sayHi  
  ↓

會往 a.__proto__ 找
  ↓

a.__proto__ === A.prototype
  ↓

A.prototype === greeting
  ↓

找到 sayHi

上面是覆蓋 prototype 的方式,也可以直接往 prototype 加東西(擴充)

function A() {}

A.prototype.sayHi = function () {
  console.log("Hi!!!")
}

const a = new A()

a.sayHi()  // Hi!!!

覆蓋跟擴充兩者有什麼區別?

覆蓋和擴充最主要的差別是覆蓋會破壞函式本身的 constructor(建構函式)

前面有說到每個函式在被建立時都會有 prototype 的屬性(預設是個物件),而那個物件裡預設會有一個 constructor ,constructor 則會指向函式本身,雙向的關係。

function Dog(name) {
  this.name = name
}

Dog.prototype.constructor === Dog  // true

不建議用覆蓋的方式去寫,如果真的要覆蓋的話要再手動補回 constructor

Dog.prototype = {
  constructor: Dog,  // 補回來
  bark: function() { console.log('汪!'); }
};

上面是 constructor 與 prototype 整體關係圖

function Dog(name) {
  this.name = name;
}

Dog.prototype.bark = function() {
  console.log(this.name + ' 汪汪!');
};

const rex = new Dog('Rex')
const lulu= new Dog('Lulu')

如果要寫物件導向程式設計時我選擇寫的方式會是

class 語法 > prototype 擴充 > prototype 覆蓋(補回constructor)

以上面的例子 class 語法的寫法會是:

class Dog {
  constructor(name){
    this.name = name
  }

  bark() {
    console.log(this.name + ' 汪汪!')
  }
}

메타데이터
post_id
a482d93edf6e
slug
js學習筆記-proto-vs-prototype-a482d93edf6e
url
https://medium.com/@lkimluu02/js%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-proto-vs-prototype-a482d93edf6e
canonical_url
https://medium.com/@lkimluu02/js%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-proto-vs-prototype-a482d93edf6e
author_url
https://medium.com/@lkimluu02
status
ok
fetched_at
2026-08-02 13:24:08