如果你在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'
我找到的方法是将对象作为自己的原型,然后通过调用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'
这是不是一个好的方法(优点/缺点是什么?)或者是否有一个我错过的更好的做法?
感谢。
答案 0 :(得分:5)
首先,我们需要修复你如何构建你的类,因为你正在绊倒一些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();
现在我们可以解决有关获取类型名称的部分。您缺少的更好的做法是不首先检查类型。从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);
}
如果使用类型名称进行调度,请考虑使用方法。它是天然的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"); }
}
变为
Cat.prototype.speak = function(){ console.log("meow"); };
Dog.prototype.speak = function(){ console.log("woof"); };
如果真的需要某种标记,你可以明确地创建一个标记,正如其他一些答案所指出的那样:
Point2D.prototype.pointType = "2D";
这里的优点是,如果您需要,您可以让多个班级具有相同的“类型”,并且您不必担心任何棘手的instanceof
或typeof
角落案件。
答案 1 :(得分:3)
我想知道你是否想要更简单的东西:
function Point2D(x, y) {
this.X = x;
this.Y = y;
}
var p = new Point2D(1,1);
alert(p instanceof Point2D); // true
编辑:
您可以添加自己的类型属性:
function Point2D(x, y) {
this.X = x;
this.Y = y;
this.type = "Point2D";
}
var p = new Point2D(1,1);
alert(p.type); // "Point2D"
你没有多说过你想知道一个物体的类型。我建议你可能想重新考虑一下。只要有可能,特定于类型的方法处理应该放在对象之间的常用方法中,这样你就可以在方法调用中请求一个动作,并且该方法在每个特定对象的方法中实现特定于类型的处理。
答案 2 :(得分:1)
Typeof
仅告诉您var x是否为:
现在variable.constructor
告诉你哪个函数实际创建了当前对象。
也有区别:
var foo = function Test(){
};
var x = new foo();
// Here, x.constructor == function Test(){};
// and x.constructor.name == 'Test'
function Bar(){
}
var y = new Bar();
// But here, y.constrcutor == 'Bar'
答案 3 :(得分:0)
你没有返回Point2D但是:
{
X: x,
Y: y
}
这显然是一个对象。
顺便说一下,你要找的是p instanceof Point2D
。
修改强>
你似乎没有找到这种模式,是吗?
function Point2D(x, y) {
var self = this;
this.X = x;
this.Y = y;
this.getX = function(){
alert(this.X);
}
}
var p = new Point2D(1,1);
p.getX();
alert(p instanceof Point2D); // true
答案 4 :(得分:0)
嗯,这很复杂。您可以从这个功能开始:
实际上jQuery中有很多很棒的功能。查看以“是”开头的所有实用程序函数:http://api.jquery.com/category/utilities/
如果这些不够好,请在此查找源代码并编写自己的变体:http://james.padolsey.com/jquery/#v=1.6.2
您也可以使用此功能:
function listProps (obj) {
console.log("constructor: "+obj.constructor);
console.log("prototype "+obj.prototype);
for (var prop in obj) {
console.log(prop+": "+obj.prop);
}
}