堆疊是一種資料結構,相較於陣列具有更多限制。

我們只能將項目加入堆疊頂部,並且只能移除堆疊頂部的項目。

想像一下一堆書。你只能從頂部添加書,並且只能從頂部移除書。

因此,如果你添加了一堆書,然後想要存取第一本添加的書,你需要先移除所有書,直到到達第一本書。

這個概念被稱為「先進後出」(First In, Last Out,FILO)。

雖然JavaScript的陣列是內建的,不需要自己建立,但我們必須自己實現堆疊。

我們將創建一個封裝我們資料的資料結構,使其無法從外部訪問,只允許使用push()方法將資料添加到堆疊中,並使用pop()方法從堆疊中移除資料。

我們可以用多種不同的方式實現這一點。其中一種方式是使用類別,尤其是我要使用私有類別欄位。私有類別欄位尚不是JavaScript標準的一部分,但自版本12起在Chrome、Edge、Safari和Node.js中可用。但在Firefox中尚不可用,希望能夠早日支援。

為什麼我使用它們?因為它們使我們能夠非常容易地封裝類別的內部狀態並保護它免受外界的訪問。

class Stack {
 #items = []
 push = (element) => this.#items.push(element)
 pop = () => this.#items.pop()
 isempty = () => this.#items.length === 0
 empty = () => (this.#items.length = 0)
 size = () => this.#items.length
}

我們有5個公共方法:pushpop用於將項目添加/移除堆疊,isempty用於檢查堆疊是否為空,empty用於清空堆疊,size用於獲取堆疊的大小。

現在,我們可以從這個類別建立堆疊物件並進行操作:

const stack = new Stack()
stack.push(1)
stack.push(2)
stack.push(3)
console.log(stack.size()) //3
console.log(stack.pop()) //[ 3 ]
console.log(stack.size()) //2

如果使用公共屬性,一切都會以相同的方式運作:

class Stack {
 items = []
 push = (element) => this.items.push(element)
 pop = () => this.items.pop()
 isempty = () => this.items.length === 0
 empty = () => (this.items.length = 0)
 size = () => this.items.length
}

只是現在我們可以從外部檢視items

const stack = new Stack()
stack.push(2)
console.log(stack.items) //[ 2 ]

而使用私有類別欄位,訪問stack.items將返回undefined