用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.

猜你喜欢

转载自blog.csdn.net/qq_39833020/article/details/83106041