【发布时间】:2011-12-10 11:21:18
【问题描述】:
我正在为来自 C# 背景的 javascript 学习更高级的 OO 策略,并且想知道如何实现基于原型的验证是否是个好主意。例如,当一个对象或函数需要它的一个参数来满足某个接口时,你可以像这样检查它的接口,
var Interface = function Interface(i) {
var satisfied = function (t, i) {
for (var key in i) {
if (typeof t !== 'object') {
return false;
}
if (!(key in t && typeof t[key] == i[key])) {
return false;
}
}
return true;
}
this.satisfiedBy = function (t) { return satisfied(t, i); }
}
// the interface
var interfacePoint2D = new Interface({
x: 'number',
y: 'number'
});
// see if it satisfies
var satisfied = interfacePoint2D.satisfiedBy(someObject);
我想出了这个策略,只通过接口验证对象,忽略对象的内部实现。
或者说你正在使用基于原型的继承,你应该还是不应该根据它们的原型函数来验证参数?我了解您将使用原型来实现默认功能,而接口未指定任何默认功能。有时,您传递给函数的对象可能需要某些默认功能才能使该函数正常工作。仅针对接口进行验证会更好,还是应该针对原型进行验证,如果是,最好的方法是什么?
编辑 -- 我提供了更多关于我为什么要问这个的上下文,
以在线游戏设计为例(主要使用 javascript 编写的游戏)。在这种情况下,我对验证感兴趣有两个主要原因,
1) 提供强大的公共 API 以根据需要修改游戏
2) 防止(或至少极大地阻止)潜在的作弊者
这需要在可定制性和滥用之间取得平衡。具体来说,一种情况是设计物理引擎,让游戏中的对象对重力做出反应。在现实系统中,用户不应该能够向系统添加对重力没有反应的对象。该系统有一个函数可以表示重力在任何给定点的全局效应:
function getGravityAt(x, y) {
// return acceleration due to gravity at this point
}
反应的对象有一个方法可以使用它来更新它们的加速度:
function update() {
this.acceleration = getGravity(this.position);
}
至少要做的事情可能是确保添加到系统中的任何对象都具有“更新”方法,但您仍然不能确保 update() 方法确实旨在对重力做出反应。如果只允许从原型 update() 方法继承的对象,那么您至少在某种程度上知道系统中的所有内容都会真实地做出反应。
【问题讨论】:
-
就个人而言,我根本不会验证。诸如 JS 或 Python 之类的动态类型语言更遵循 duck typing 的概念……如果它听起来和看起来像鸭子,那就是鸭子。如果您的函数需要与某个接口兼容的参数并且没有得到它......那么它无论如何都会抛出错误。正确使用您的代码是其他程序员的责任。
-
如果您开发一个 javascript 游戏或 API 并希望防止滥用框架怎么办?我认为明确定义的接口是个好主意,尤其是在 API 设计中。
-
当然接口应该明确定义并有据可查。不要误会我的意思,这总是很重要的。但是imo你不应该在运行时检查它们。
-
如果你有一个函数(x, y) 需要一个点并且有人传入一个本身已经包含属性'x'和'y'的对象,你通常会这样做:if(xx && xy) { } 检查这样的对象,以便函数可以单独接受点对象或每个坐标。那本质上不是接口检查吗?我的课程的重点只是以不那么冗长的方式启用该功能(对于更复杂的对象,您的 if 语句会变得很长)。
标签: javascript oop inheritance interface prototype-programming