为什么更改函数的 .prototype 会影响已使用该构造函数创建的对象的“实例”
Why does changing the .prototype of a Function affect "instanceof" for objects already created with that constructor function
我试图做的是在Javascript中创建一个简单的对象层次结构,其中层次结构中的每个对象都有自己的一组属性,同时能够在这些新创建的对象上使用instanceof。 换句话说,我希望我的基本对象(请参阅下面的 People)实际包含 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
?
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
这里的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
instanceof
运算符查看实例上缓存的原型链,并将其与您提供给它的构造函数进行比较。如果更改了构造函数上的原型,则它们不再匹配。
如果不完全更改原型对象,而只是更新属性,则不会发生这种情况。
您的对象模型看起来很奇怪;为什么名称不是实例属性,就像"皮带颜色"一样?
- 文本表示法VS.构造函数,用于在JavaScript中创建对象
- 使用sinon.js创建一个“;“间谍对象”;使用基于真实构造函数/原型的间谍方法
- 对使用函数构造函数创建的函数的内部引用
- 获取使用函数构造函数创建的函数的名称
- 创建 JavaScript 构造函数时的语法错误
- 为什么可以't JavaScript构造函数创建字符串或数字
- 如何在构造函数中创建一个简单的DOM元素,并在调用时将其附加到元素中
- 为什么用构造函数创建对象会执行对象's方法
- 我应该在原型上还是在新创建的实例上调用构造函数方法
- 使用构造函数创建对象和返回对象有区别吗
- 是否可以在函数构造函数中识别哪个对象调用它,并在错误的对象调用时中止创建
- 构造函数中的方法和创建构造函数后函数上的方法有什么区别
- 创建构造函数的构造函数 (JavaScript)
- 如何在 angularjs 中为控制器创建构造函数
- Angular 1.4.8/JS:创建构造函数并将属性继承到第三个对象中
- 如何创建构造函数Count
- AngularJS设计模式:我应该使用工厂来创建构造函数吗
- 在Javascript中,函数声明是创建构造函数的唯一方法
- 使用Object.keys获取用于创建构造函数实例的属性,然后打印继承的属性
- 是否只创建构造函数的一个实例