X.prototype.X也将X添加到基类中 我精通C++,所以在OOP中有很好的背景,但是我对JavaScript很新,我想了解如何正确地在JavaScript中实现多态性。我已经阅读了许多与本主题相关的教程和StackOverflow问题,但没有一个详细解释如何正确地从基类继承以及如何向子类添加新成员 function Obj1() {} function Obj2() {} function Obj3() {} Obj2.prototype === Obj3.prototype; // false

X.prototype.X也将X添加到基类中 我精通C++,所以在OOP中有很好的背景,但是我对JavaScript很新,我想了解如何正确地在JavaScript中实现多态性。我已经阅读了许多与本主题相关的教程和StackOverflow问题,但没有一个详细解释如何正确地从基类继承以及如何向子类添加新成员 function Obj1() {} function Obj2() {} function Obj3() {} Obj2.prototype === Obj3.prototype; // false,javascript,polymorphism,Javascript,Polymorphism,好奇1:如果Obj2和Obj3(以及就此而言,Obj1)都继承自对象,为什么它们的原型不相同?Obj2和Obj3是否各自收到了自己的对象的副本 Obj2.prototype = Object; Obj2.prototype = Object; Obj2.prototype === Obj3.prototype; // true Obj2.prototype = Obj1; Obj3.prototype = Obj1; Obj2.prototype === Obj3.prototype; //

好奇1:如果
Obj2
Obj3
(以及就此而言,
Obj1
)都继承自
对象,为什么它们的原型不相同?
Obj2
Obj3
是否各自收到了自己的
对象的副本

Obj2.prototype = Object;
Obj2.prototype = Object;
Obj2.prototype === Obj3.prototype;  // true
Obj2.prototype = Obj1;
Obj3.prototype = Obj1;
Obj2.prototype === Obj3.prototype;  // true
好奇2:在这两种情况下,
Obj2
Obj3
现在共享相同的原型。发生了什么变化

Obj2.prototype.pi = function() {  return 3.14159;  }
Obj2.prototype.pi();  // 3.14159
Obj3.prototype.pi();  // 3.14159
Obj1.pi();  // 3.14159
真正的问题:更改
Obj2
的原型也会更改
Obj3
的原型和功能
Obj1
本身。对于C++程序员来说,这是非常令人震惊的,尽管这正是我从上述语法中所期望的:毕竟,由于 Obj2和 Obj3的原型都等同于 OBJ1,对一个的改变将对另两个产生相同的改变。然而,我想使用
Obj1
作为
Obj2
Obj3
的基类,并在
Obj2
上插入一个新函数,该函数不以任何方式被
Obj1
Obj3
共享。我该怎么做

当实例化这些对象时,会出现更多的奇怪现象:

var x = new Obj2();
x.pi();  // 3.14159
var y = new Obj3();
y.pi();  // 3.14159
var z = new Obj1();
z.pi();  // Error: pi() not defined on z.

Obj2
Obj3
都有一个函数
pi()
,这意味着它们仍然共享一个包含函数
pi()
的基类。这个基类正是
Obj1
——但是
Obj1
的实例不包含
pi()
,尽管有相反的证据

prototype
属性也返回一个对象,该对象是object的实例,但不是同一个实例,因此它们不是同一个对象,对等式的比较自然返回false

更详细地说,Obj1、Obj2和Obj3都是函数和对象,它们的原型也是对象。在C++术语中,将>原型< /Cord>属性作为指向另一个对象的指针,而不是类定义或基类。 对于Obj2,您可以声明一个单独的方法,如下所示:

function Obj2() {
    this.prototype = new Obj1();
    this.myOwnMethod = function (x) { ... }
}
var A = function () {};
A.prototype.foo = function () {};
var a = new A();

var B = function () {};
B.prototype = a; // or new A(); -- an object which can live-lookup the prototype of A
// problem is, `constructor` on the prototype will now point to `A`, so...
B.prototype.constructor = B; // now b instanceof B should work in tests
B.bar = function () {};


var b = new B();
b.foo(); // A.prototype.foo
b.bar(); // B.prototype.bar
我试图用我自己的话来写一个关于Javascript面向对象的好解释,但我认为这会花太长时间:)相反,我决定删除我写的半连贯的文本,并给出两个指针,帮助我更深入地理解它,希望它们也能帮助你:

使用或其他框架为您提取此信息。要让继承像您期望的那样工作,需要做很多手脚。

在您的第一个证明中:

function a () {};
function b () {};

a.prototype === b.prototype; // false
您发现,
原型
不是
对象
——它不是基类。 它是一个对象,它又被扩展,原型化,具有
object
的方法和属性
以及
{}=={}的任何测试
将返回false,始终,除非您正在测试指向同一对象的两个指针:

var a = {},
    b = a;

a === b; // true
继承TrainCrank之后直接指向缺少这个概念,因为您将所有三个函数都设置为指向同一个对象(最初指向
对象本身,然后指向
Obj1
的原型对象)。
prototype
live,对象构造后对原型的任何更改都将反映在包含指向该对象指针的对象中

您已经给了
Obj1
Obj2
Obj3
一个指向完全相同对象的指针。
因此,当您尝试访问某个属性时(而不是生活在某个静态、预编译、GOTO状态),对它们共享的原型对象的任何修改都将反映在所有构造的对象中,因为继承解析是实时发生的

如果您想要子类化的能力,您可以这样做:

function Obj2() {
    this.prototype = new Obj1();
    this.myOwnMethod = function (x) { ... }
}
var A = function () {};
A.prototype.foo = function () {};
var a = new A();

var B = function () {};
B.prototype = a; // or new A(); -- an object which can live-lookup the prototype of A
// problem is, `constructor` on the prototype will now point to `A`, so...
B.prototype.constructor = B; // now b instanceof B should work in tests
B.bar = function () {};


var b = new B();
b.foo(); // A.prototype.foo
b.bar(); // B.prototype.bar
但事实上,如果你想把这一点延伸得太远,你会让自己发疯的。

JS中遵循的一条更为完善的路径是基于组件的对象构造和依赖注入。

首先要做的是完全接受JavaScript中继承与C++中的继承完全不同的事实。这真的只是表面上的关系;它基于一个完全不同的概念模型。哦,特别是,JavaScript中没有“类”这样的概念。有一些效果可以让你假装有课程,但这只是一个惯例。我建议你从阅读开始,你可能也对阅读感兴趣。请尝试回答问题,不要提供切线。这不是切线。如果你在做JS开发并试图使用原始原型,那你就错了。:)好吧,现在这个讨论是另一个无用的切线。更多地了解你的工作内容和工作方式没有坏处。那些有骨气的人确实读过书,所以他们错了?这是浪费时间,时间就是金钱。如果我是OP团队的开发人员,我会告诉他不要再胡闹了,使用一个框架。这就是目前javascript开发的现状。你使用一个框架。从C++迁移的人可能不知道这一点。我相信知道比盲目相信要好,或者更糟糕的是不知道、不关心和略过。时间就是金钱,从长远来看,这可以节省更多的金钱和时间。