gjv*_*lya 5 javascript closures
例如,看一下我对堆栈的简单实现:
var MyStack = (function() {
var min;
var head;
// Constructor
function MyStack() {
this.size = 0;
}
MyStack.prototype.push = function(val) {
var node = new Node(val);
if (typeof min === 'undefined' || val < min) {
min = val;
}
++this.size;
if (typeof head === 'undefined') {
head = node;
} else {
node.next = head;
head = node;
}
};
MyStack.prototype.pop = function() {
if (typeof head === 'undefined') {
throw new Error('Empty stack');
}
--this.size;
var data = head.data;
head = head.next;
return data;
};
MyStack.prototype.min = function() {
if (typeof min === 'undefined') {
throw new Error('Min not defined');
}
return min;
};
MyStack.prototype.peek = function() {
if (typeof head === 'undefined') {
throw new Error('Empty stack');
}
return head.data;
};
function Node(data) {
this.data = data;
this.next;
}
return MyStack;
})();
Run Code Online (Sandbox Code Playgroud)
通过使用这种方法,我可以确保没有人能够(意外或有意)操纵"私人"字段,如min和head.我还可以使用不需要公开的Node()等私有函数.
我已经读过这将使用更多内存,因为它必须为为MyStack创建的每个新对象维护一个额外的范围.它需要这么多额外的内存,这种方式是个坏主意吗?
我确实尝试通过使用原型来优化它,而不是每次创建新对象时创建函数.换句话说,我没有将函数作为MyStack构造函数的一部分包含在内.
我的问题是,这是一个糟糕的设计吗?这种方法有任何重大缺陷吗?
使用闭包来模拟封装是一个坏主意吗?
不。虽然我不认为这是“模拟”,但闭包正在实现封装。
我确实尝试通过使用原型来优化它,而不是每次创建新对象时都创建函数。换句话说,我没有将这些函数包含在 MyStack 构造函数中。
我的问题是,这样的设计很糟糕吗?这种方法有什么重大缺陷吗?
是的,这实际上是错误的。您的minand head(and 和MyStack)Node变量本质上是static。它们仅定义一次,并将由所有实例共享。您不能创建两个不同的堆栈,它们都将具有相同的head引用。
要封装每个实例的状态,您需要在构造函数中声明变量,以便使用每个新对象创建它们。为此,您还必须在构造函数范围中声明需要访问它们的所有方法(“特权”)。
var MyStack = (function() {
function MyStack() {
var size = 0;
var head = undefined;
function checkNonEmpty() {
if (typeof head === 'undefined') {
throw new Error('Empty stack');
}
}
this.push = function(val) {
size++;
head = new Node(val, head);
};
this.pop = function() {
checkNonEmpty();
this.size--;
var data = head.data;
head = head.next;
return data;
};
this.peek = function() {
checkNonEmpty();
return head.data;
};
this.getSize = function() {
return size;
};
}
function Node(data, next) {
this.data = data;
this.next = next;
}
return MyStack;
})();
Run Code Online (Sandbox Code Playgroud)
如果要将这些方法放在原型上,则需要将head和size值设置为实例的属性。
| 归档时间: |
|
| 查看次数: |
167 次 |
| 最近记录: |