我正在尝试做的是在Javascript中创建一个简单的对象层次结构,其中层次结构中的每个对象都有自己的一组属性,同时能够在这些新创建的对象上使用instanceof。换句话说,我希望我的基础对象(请参阅下面的人)实际包含firstName和lastName属性。我最终并不希望我的所有属性都被混合到同一个“这个”上。我想要一个漂亮/干净的真实对象层次结构。
要做到这一点,我认为这是正确的方法,但看起来我错了:
var Person = function (firstName, lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
var Ninja = function (beltColor)
{
this.beltColor = beltColor;
}
Ninja.prototype = new Person ("George", "Clooney");
var ninja1 = new Ninja ("Black");
Ninja.prototype = new Person ("Scarlett", "Johansson");
var ninja2 = new Ninja ("Blue");
Ninja.prototype = new Person ("Brad", "Pitt");
var ninja3 = new Ninja ("Green");
console.log (ninja1 instanceof Ninja); // false
console.log (ninja1 instanceof Person); // true
console.log (ninja2 instanceof Ninja); // false
console.log (ninja2 instanceof Person); // true
console.log (ninja3 instanceof Ninja); // true
console.log (ninja3 instanceof Person); // true
上面的代码(在我看来)会使用Ninja构造函数有效地创建三个主要对象,结果ninja1.__proto__, ninja2.__proto__ and ninja3.__proto__
对象将包含firstName / lastName属性(这就是我想要的)。这些__proto__对象也可以是“type”Person,因为它们是用Person构造函数创建的,ninja1,ninja2和ninja3对象的类型为“Ninja”(或者我认为),因为它们是用Ninja创建的构造
我意识到通过Person构造函数将Ninja.prototype重新分配给新创建的对象就是抛出instanceof
运算符,但对于我的生命,我不知道为什么。< / p>
所以我有两个问题:
1)为什么通过Person构造函数将Ninja.prototype重新分配给新创建的对象会抛弃instanceof
运算符?
2)做我想做的事情的正确方法是什么?换句话说,创建一个简单的对象层次结构,其中属性真正处于层次结构的不同级别,同时还能够以有意义的方式使用instanceof
?
答案 0 :(得分:1)
Q1:为什么通过Person构造函数将Ninja.prototype重新分配给新创建的对象会抛弃instanceof
运算符?
这样做是因为instanceof
运算符通过上升原型链并检查对象的内部实际原型([[Prototype]]
)是否与构造函数的当前prototype属性进行比较来工作。 / p>
Q2:做我正在尝试做的事情的正确方法是什么?换句话说,创建一个简单的对象层次结构,其中属性真正处于层次结构的不同级别,同时还能够以有意义的方式使用instanceof
?
原型适用于构造函数的所有实例共有的项目(例如,所有人都有大脑,但不是每个人都有相同的名称)。而不是更改原型,直接添加名字和姓氏参数作为Ninja
函数实例的属性,并使Ninja
的原型属性为空Person
(以覆盖一个没有名字的人的情况,以便instanceof
返回true):
var Person = function (firstName, lastName)
{ this.firstName = firstName;
this.lastName = lastName;
}
var Ninja = function (beltColor, firstName, lastName)
{ this.beltColor = beltColor;
Person.call(this, firstName, lastName); // call parent function
}
Ninja.prototype = new Person("", ""); // do this so that instanceof returns true
var ninja1 = new Ninja ("Black", "George", "Clooney");
var ninja2 = new Ninja ("Blue", "Scarlett", "Johansson");
var ninja3 = new Ninja ("Green", "Brad", "Pitt");
console.log (ninja1 instanceof Ninja); // true
console.log (ninja1 instanceof Person); // true
console.log (ninja2 instanceof Ninja); // true
console.log (ninja2 instanceof Person); // true
console.log (ninja3 instanceof Ninja); // true
console.log (ninja3 instanceof Person); // true
答案 1 :(得分:1)
这里的instanceOf
方法没有给出Ninja对象的构造函数,因为你已经手动将NInja对象的原型分配为“Person”,所以当遍历原型链时它会有Person对象。如果您期待您想要的,可以尝试下面的代码
var Person = function (firstName, lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
var Ninja = function (firstName, lastName, beltcolor)
{
this.beltColor = beltColor;
Person.apply(this,arguments);
}
var ninja1 = new Ninja ( "George", "Clooney", "Black");
var ninja2 = new Ninja ("Scarlett", "Johansson","Blue");
var ninja3 = new Ninja ("Brad", "Pitt", "Green");
console.log (ninja1 instanceof Ninja); // true
console.log (ninja1 instanceof Person); // false
console.log (ninja2 instanceof Ninja); // true
console.log (ninja2 instanceof Person); // false
console.log (ninja3 instanceof Ninja); // true
console.log (ninja3 instanceof Person); // false
console.log(ninja1.firstName); //George
希望这会对你有所帮助。
您还可以查看以下链接https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
答案 2 :(得分:0)
instanceof
运算符查看实例上的缓存原型链,并将其与您提供的构造函数进行比较。如果你在构造函数上更改了原型,它们将不再匹配。
如果你没有完全改变原型对象,只是更新属性,那就不会发生。
你的对象模型看起来很奇怪;为什么名称不是实例属性,就像“带颜色”一样?