【问题标题】:Prototypes and property inheritance. Why is a property missing?原型和属性继承。为什么缺少一个属性?
【发布时间】:2017-05-18 15:44:30
【问题描述】:

让我们考虑下面的代码:

// Let's create a constructor "Point".

let Point = function(x,y) { this.x = x; this.y = y; };
Point.prototype = { x:null, y:null, print: function() { console.log("(" + this.x + "," + this.y + ")")} };

let p = new Point(1,2);
p.print();
console.log(Object.getPrototypeOf(p)); // => { x: null, y: null, print: [Function: print] }
console.log(Point.prototype === Object.getPrototypeOf(p)); // => true
console.log(p.constructor); // => Object
console.log(p.constructor.name); // => Object
console.log(p.constructor === Point); // => false
console.log(p.constructor === Object); // => true
console.log(p.prototype); // undefined
console.log(p instanceof Point); // => true
console.log(typeof p); // => Object
console.log();

// Let's create the constructor "Pigment" that derives from "Point".

let Pigment = function(x,y,c) {
    Point.call(this, x, y);
    this.color = c;
};
Pigment.prototype = new Point;
Pigment.prototype.paint = function () {
    console.log(this.color);
};

let pi = new Pigment(1,2,'red');
console.log(pi);
pi.print();
pi.paint();
console.log(Object.getPrototypeOf(pi)); // => (Pigment) { x: undefined, y: undefined, paint: [Function] }
console.log(pi instanceof Object); // => true
console.log(pi instanceof Point); // => true
console.log(pi instanceof Pigment); // => true
console.log(pi.constructor === Object); // => true
console.log(pi.__proto__); // => (Pigment) { x: undefined, y: undefined, paint: [Function] }
console.log(pi.__proto__.__proto__); // => (Point) { x: null, y: null, print: [Function: print] }
console.log(pi.print); // => [Function: print]
console.log(pi.__proto__ === Object.getPrototypeOf(pi)); // => true
console.log(pi.__proto__ == Pigment.prototype); // => true
console.log(pi.__proto__.__proto__ === Point.prototype); // => true

构造函数“Point”的原型是:

{
    x:null,
    y:null,
    print: function() { console.log("(" + this.x + "," + this.y + ")")}
}

构造函数“Pigment”的原型是“Point”的一个实例:

Pigment.prototype = new Point;

因此我希望与构造函数“Pigment”关联的原型包含属性“print”。然而,事实并非如此。确实:

console.log(pi.__proto__);

打印:

{ x: undefined, y: undefined, paint: [Function] }

为什么缺少“print”属性?

--编辑--

以下示例按预期工作:

var util = require("util");

function Person(age) {
    this.age = age;
}
Person.prototype = {
    age: null,
    print : function(){
        console.log("This person is " + this.age + " years old.");
    }
};

function Student(age, level) {
    Person.call(this, age);
    this.level = level;
}

Student.prototype = new Person;
Student.prototype.level = null;
Student.prototype.talk = function () {
    console.log("I talk");
};


Student.prototype.constructor = Student;
var b = new Student(10, 5);
b.print();
console.log(b.constructor);
console.log("b.proto:\n" + util.inspect(b.__proto__) + "\n");
console.log("b.proto.proto:\n" + util.inspect(b.__proto__.__proto__) + "\n");

请注意添加的行:

Student.prototype.constructor = Student;

输出是:

This person is 10 years old.
[Function: Student]
b.proto:
Student {
  age: undefined,
  level: null,
  talk: [Function],
  constructor: [Function: Student] }

b.proto.proto:
{ age: null, print: [Function: print] }

这是正确的。

现在,让我们按照 MeteorZero 的建议去做:让我们替换

Student.prototype = new Person;

作者:

Student.prototype = Person.prototype;

那么,结果是:

This person is 10 years old.
[Function: Student]
b.proto:
Student {
  age: null,
  print: [Function: print],
  level: null,
  talk: [Function],
  constructor: [Function: Student] }

b.proto.proto:
{}

这不是我们所期望的。

【问题讨论】:

  • 信息可能相关:node -v v6.9.5
  • 我忘了这个Student.prototype.constructor = Student;,干得好

标签: javascript inheritance properties prototype


【解决方案1】:

您在这里的假设是错误的Pigment.prototype = new Point;。您为 Pigment.prototype 而不是 Point.prototype 对象分配了新的 Point 对象。我已经修改了你的作业,所以现在可以使用打印功能了

// Let's create a constructor "Point".

let Point = function(x,y) { this.x = x; this.y = y; };
Point.prototype = { x:null, y:null, print: function() { console.log("(" + this.x + "," + this.y + ")")} };

let p = new Point(1,2);
p.print();
console.log(Object.getPrototypeOf(p)); // => { x: null, y: null, print: [Function: print] }
console.log(Point.prototype === Object.getPrototypeOf(p)); // => true
console.log(p.constructor); // => Object
console.log(p.constructor.name); // => Object
console.log(p.constructor === Point); // => false
console.log(p.constructor === Object); // => true
console.log(p.prototype); // undefined
console.log(p instanceof Point); // => true
console.log(typeof p); // => Object
console.log();

// Let's create the constructor "Pigment" that derives from "Point".

let Pigment = function(x,y,c) {
    Point.call(this, x, y);
    this.color = c;
};
// Pigment.prototype = new Point;
Pigment.prototype = Point.prototype;
Pigment.prototype.paint = function () {
    console.log(this.color);
};

let pi = new Pigment(1,2,'red');
console.log(pi);
pi.print();
pi.paint();
console.log(Object.getPrototypeOf(pi)); // => (Pigment) { x: undefined, y: undefined, paint: [Function] }
console.log(pi instanceof Object); // => true
console.log(pi instanceof Point); // => true
console.log(pi instanceof Pigment); // => true
console.log(pi.constructor === Object); // => true
console.log("pi.__proto__::", pi.__proto__); // => (Pigment) { x: undefined, y: undefined, paint: [Function] }
console.log(pi.__proto__.__proto__); // => (Point) { x: null, y: null, print: [Function: print] }
console.log(pi.print); // => [Function: print]
console.log(pi.__proto__ === Object.getPrototypeOf(pi)); // => true
console.log(pi.__proto__ === Pigment.prototype); // => true
console.log(pi.__proto__ === Point.prototype); // => true

【讨论】:

  • 是的,我试过这个......但是,它打破了(至少据我所知)原型链。代码console.log(pi.__proto__.__proto__); 打印{}
  • 是的,它确实坏了,因为你从一开始就设置错了。
  • 如果你想要console.log(pi.__proto__.__proto__ === Point.prototype); // => true 然后删除一个__proto__ 然后你就会有console.log(pi.__proto__ === Point.prototype); // => true
  • 那么实现继承的正确方法是什么?我尝试了很多方法,但似乎都没有按预期工作。
  • 我的做法。你想颜料从点延伸然后Pigment.prototype = Point.prototype
猜你喜欢
  • 2023-03-16
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多