1

我正在尝试做的是在 Javascript 中创建一个简单的对象层次结构,其中层次结构中的每个对象都有自己的一组属性,同时能够在这些新创建的对象上使用 instanceof。换句话说,我希望我的基础对象(参见下面的 Person)实际上包含 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__ 对象也将属于“类型”Person,因为它们是使用 Person 构造函数创建的,而 ninja1、ninja2 和 ninja3 对象将属于“Ninja”类型(或者我认为),因为它们是使用 Ninja 创建的构造函数。

我意识到通过 Person 构造函数将 Ninja.prototype 重新分配给新创建的对象是instanceof运算符的抛出,但对于我的生活,我不知道为什么。

所以我有两个问题:

1) 为什么通过 Person 构造函数将 Ninja.prototype 重新分配给新创建的对象会抛出instanceof操作符?
2)做我想做的事情的正确方法是什么?换句话说,创建一个简单的对象层次结构,其中属性真正位于层次结构的不同级别,同时还能够以instanceof有意义的方式使用?

4

3 回答 3

1

Q1:为什么通过 Person 构造函数将 Ninja.prototype 重新分配给新创建的对象会抛出instanceof操作符?

这样做是因为instanceof操作符的工作方式是沿着原型链向上并检查对象的内部实际原型 ( [[Prototype]]) 是否与构造函数的当前原型属性进行比较。

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
于 2013-10-30T13:26:11.483 回答
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

于 2013-10-30T13:40:47.177 回答
0

运算符查看实例上缓存的instanceof原型链,并将其与您提供的构造函数进行比较。如果您更改了构造函数上的原型,它们将不再匹配。

如果您不完全更改原型对象,而只是更新属性,那将不会发生。

您的对象模型似乎很奇怪;为什么名称不是实例属性,就像“皮带颜色”一样?

于 2013-10-30T13:25:23.707 回答