Sea*_*man 15 javascript constructor types typechecking
如果你在javascript中有一个对象的实例,那么它似乎很难找到它的实际类型,即
var Point2D = function Point2D(x, y) {
return {
X: x,
Y: y
}
}
var p = new Point2D(1,1);
typeof p // yields just 'Object' not 'Point2D'
Run Code Online (Sandbox Code Playgroud)
我找到的一种方法是将对象作为自己的原型,然后通过调用prototype.constructor.name可以有效地获取其名称,
var Point2D = function Point2D(x, y) {
return {
X: x,
Y: y,
prototype: this
}
}
new Point2D(1,1).prototype.constructor.name // yields 'Point2D'
Run Code Online (Sandbox Code Playgroud)
这是不是一个好的方法(优点/缺点是什么?)还是我错过了更好的做法?
谢谢.
首先,我们需要修复你如何构建你的类,因为你正在绊倒一些JS陷阱并做一些非常奇怪的事情:
function Point2D(x, y){
//Our constructor/initialization function
//when run, the 'this object will have
//Point2D.prototype as its prototype
this.x = x;
this.y = y;
//Don't return a value here! Doing so overrides
//the default "return this" that we actually want.
}
//You can put things in the Point2D prototype in order to have them
//be shared by all Point2D objects. Normally you want the methods to be shared.
Point2D.prototype.getX = function(){
return this.x;
};
//Note that there is nothing magical about the "prototype" property.
//It is just where the `new` syntax expects the prototype it will use to be.
//The actual magic property is __proto__ (don't depend on it though
// __proto__ is browser specific and unsafe/evil)
//We now can create points!
var p = new Point2D(17.0, 42.0);
p.getX();
Run Code Online (Sandbox Code Playgroud)
现在我们可以解决有关获取类型名称的部分.您缺少的更好的做法是不首先检查类型.从OO的角度来看,对象的实现方式(ts类)无关紧要,但它的行为方式和界面(暴露的方法和属性)是什么.此外,从Javascript的角度来看,类型名称是一种二级黑客,它与实际使用的原型OO方案不太匹配.
由于您可能首先尝试检查类型名称的原因有很多,因此有许多不同的"最佳"解决方案.我能想到的一些:
如果你所说的只是"这个对象实现了一个特定的点接口"那么你可以直接进行特征检查:
function isPoint(p){
//check if p has all the methods I expect a point to have:
//(note that functions are truthy in a boolean context)
return (p.getX && p.getY);
}
Run Code Online (Sandbox Code Playgroud)如果使用类型名称进行调度,请考虑使用方法.它是天然的OO方式.
function speak(obj){
//fake pseudo-syntax:
if(obj is of type Cat){ console.log("meow"); }
if(obj is of type Dog){ console.log("woof"); }
}
Run Code Online (Sandbox Code Playgroud)
变
Cat.prototype.speak = function(){ console.log("meow"); };
Dog.prototype.speak = function(){ console.log("woof"); };
Run Code Online (Sandbox Code Playgroud)如果你真的需要某种标记,你可以明确地创建一个标记,正如其他一些答案所指出的那样:
Point2D.prototype.pointType = "2D";
Run Code Online (Sandbox Code Playgroud)
这里的优点是,如果需要,您可以让多个类具有相同的"类型",并且您不必担心任何棘手instanceof或typeof极端情况.