我正在开始一个相当大的JS项目的工作,并希望确保我干净,高效地构建代码。我一直在阅读大量关于JS中OOP的不同方法,但没有找到我真正喜欢的方法。
我很欣赏使用prototype
属性提供的性能改进,但是当您尝试将真正的私有方法和变量添加到混合中时,它会变得相当混乱。另一方面,我非常喜欢closure
方法,但我对降低的性能感到不满意。我查看了module
模式,但发现它非常详细。某处是否有幸福的媒介?
为了说明我正在努力解决的问题,这里有两个非常小的样本类:
点类:
function Point(x, y) {
this.x = x;
this.y = y;
}
// Get the x coordinate.
Point.prototype.getX = function() {
return this.x;
}
// Get the y coordinate.
Point.prototype.getY = function() {
return this.y;
}
// Get the (x, y) coordinate.
Point.prototype.getXY = function() {
return {x: this.x, y: this.y};
}
// Set the x coordinate.
Point.prototype.setX = function(x) {
this.x = x;
}
// Set the y coordinate.
Point.prototype.setY = function(y) {
this.y = y;
}
// Set the (x, y) coordinate.
Point.prototype.setXY = function(x, y) {
this.x = x;
this.y = y;
}
用户类:
function User(guid) {
var guid = guid;
// Return the user's GUID.
this.getGuid = function() {
return guid;
}
}
在任何一个给定时间内可能会有数千个点对象在使用,所以我觉得prototype
方法是那里的最佳选择。但是,如果我想在坐标设置中添加任何验证,只需调用Point.x = <value>
就可以绕过它。同样,我可能会在大多数时间调用Point.getXY()
,这将构建基本上属于公共属性的新对象。我应该摆脱Point
类的getter和setter的概念,让它创建完全开放的公共对象吗?在OOP的背景下,这似乎是错误的。
对于User
类,我想在内部存储一个GUID,以便可以请求但从不修改。使用prototype
方法无法完成此操作(除非我遗漏了某些内容),因此我不得不使用某种closure
。我预见一次有数百名用户在运行,因此性能不如Point
类那么重要。但是,我并不想在整个代码库中切换不同类型的OOP样式。
所以,作为一个普遍的问题,是否有一种方法可以解决JS中的OOP问题,这种方法可以让我在清除私有化选择函数和变量的同时使用prototype
属性?或者,我是否朝错误的方向看?我应该以不同的方式接近这个吗?
答案 0 :(得分:1)
您只能使用_
前缀等文档和约定将方法标记为“内部”,但javascript中没有真正的强制私有对象成员。
闭包是不可接受的 - 它们将拥有数据而不是可能具有“有趣”结果的对象,尤其是当想要以这种方式使用闭包来扩展“类”时。 另一点是你将使用O(n)内存来存储所有的功能对象,如果它对于库的用户来说是不受控制的,那么它可以非常容易地使用库,从而导致记忆问题。
您可以像下面这样使用下划线前缀约定:
function Point(x, y) {
this._x = x;
this._y = y;
}
// Get the x coordinate.
Point.prototype.getX = function() {
return this._x;
}
// Get the y coordinate.
Point.prototype.getY = function() {
return this._y;
}
答案 1 :(得分:0)
我不知道你的背景但可能是oop,所以请查看coffee-script
答案 2 :(得分:0)
由于基于原型的面向对象不是真正的面向对象,我想你可能看错了地方。
基于原型的对象是它们子类的任何克隆。因此,如果您声明您的对象具有属性getXY(),那么它对从中克隆的任何内容都是开放的。
所以我想真正的问题是,您认为私人功能会在此实施中为您带来什么?
如果你真的需要私人功能,我会鼓励你处理你在封闭模式中必须处理的混乱。
答案 3 :(得分:0)
您可以在开发期间使用闭包方法,因此您知道没有人绕过验证,然后在发布代码时切换到更快的原型方法。
var Release = true;
if (Release) {
function Point(x, y) {
this.x = x;
this.y = y;
}
// Get the x coordinate.
Point.prototype.getX = function () {
return this.x;
}
// Get the y coordinate.
Point.prototype.getY = function () {
return this.y;
}
// Get the (x, y) coordinate.
Point.prototype.getXY = function () {
return {
x: this.x,
y: this.y
};
}
// Set the x coordinate.
Point.prototype.setX = function (x) {
this.x = x;
}
// Set the y coordinate.
Point.prototype.setY = function (y) {
this.y = y;
}
// Set the (x, y) coordinate.
Point.prototype.setXY = function (x, y) {
this.x = x;
this.y = y;
}
} else {
function Point(x, y) {
var _x = x,
_y = y;
return {
// Get the x coordinate.
getX: function () {
return _x;
},
// Get the y coordinate.
getY: function () {
return _y;
},
// Get the (x, y) coordinate.
getXY: function () {
return {
x: _x,
y: _y
};
},
// Set the x coordinate.
setX: function (x) {
_x = x;
},
// Set the y coordinate.
setY: function (y) {
_y = y;
},
// Set the (x, y) coordinate.
setXY: function (x, y) {
_x = x;
_y = y;
}
}
}
}