1. 程式人生 > >用Javascript實現棧結構

用Javascript實現棧結構

github主頁:https://github.com/A15162252289

什麼是棧?

是一種遵從後進先出(LIFO)原則的有序集合。新新增的或待刪除的元素都儲存在棧的同一端,稱之為棧頂,另一端則為棧底。在棧裡,新元素靠近棧頂,舊元素靠近棧底。

如何實現棧?

1.首先宣告一個類,並初始化一個數組用來儲存棧裡的元素:

function Stack (){
	let items=[];
}

2.為棧宣告一些方法:

push():向棧中新增元素到棧頂
pop():移除棧頂的元素並返回被移除的元素
peek():僅返回棧頂的元素不做其他任何操作
isEmpty()

:判斷棧中是否存在元素
clear():清空棧
size():返回棧中元素的個數

以下為程式碼實現:

this.push = function (element) {
	items.push(element);
}
this.pop = function () {
	return items.pop();//返回棧頂的元素
}
this.peek = function () {
	return items[items.length-1];
}
this.isEmpty = function () {
	return items.length == 0;
}
this.size = function
() { return items.length; } this.clear = function () { items = []; }

3.使用ES6語法宣告Stack類

class Stack {
	constructor () {
		this.items=[];
	}
	push(element) {
		this.items.push(element);
	}
	pop() {
		return this.items.pop();
	}
	peek() {
		return this.items[items.length-1];
	}
	isEmpty() {
		return
this.items.length == 0; } size() { return this.items.length; } clear() { this.items = []; } }

4.ES6類的缺陷

我們知道,在ES6中的類只是個語法糖,只是寫著方便。實際上類還是基於原型的。雖然基於原型的類比基於函式的類更省記憶體,也更適合建立多個例項,但不能宣告私有屬性或方法。之前我們建立的Stack類中items陣列是公用的,這是極其危險的行為。
有兩種解決辦法


  • 使用ES6限定作用域Symbol實現類(假的私有變數)
let _items=Symbol();
class Stack {
	constructor () {
		this[_items] = [];	
	}
	//其他方法中把之前的this.items全部替換為this[_items]
}

然而在ES6中還是可以通過Object.getOwnPropertySymbols取得類中宣告的所有Symbols屬性:

let stack = new Stack();
let objectSymbols = Objcet.getOwnPropertySymbols(stack);
stack[objectSymbols[0]].shift();//可以進行任意的陣列操作!

由此我們可以看出並沒有創造一個真正的私有變數

  • 使用ES6WeakMap實現類
const items = new WeakMap();//建立WeakMap例項
class Stack {
	constructor () {
		items.set(this,[]);//設定鍵值	
	}
	push (element) {
		let s = items.get(this);//根據鍵取得值
		s.push(element);
	}
	//其他方法
}

不難發現items是個全域性變數,因此我們還需要個閉包(外層函式)把Stack類包起來:

	let Stack = (function () {
		const items = new WeakMap();//建立WeakMap例項
		class Stack {
			constructor () {
				items.set(this,[]);//設定鍵值	
			}
		push (element) {
			let s = items.get(this);//根據鍵取得值
			s.push(element);
		}
		//其他方法
		return Stack;
	})()

這種方法創造了一個完全私有的變數,使得擴充套件類也無法繼承這個私有屬性。




總結:javascript是基於原型的,沒有最好的辦法為類建立私有變數和方法,使用哪種方法取決於要處理的資料量,要創造的例項個數,以及其他約束條件。最終還是取決於你。(方法待補充)

Github原始碼連結:link.