JavaScript - 为什么...继承
JavaScript - For what reason… Inheritance
谁能告诉我,为什么允许这样做(?):
function A()
{
A.prototype.getA = function()
{
return "A!";
}
}
function B()
{
B.prototype.getB = function()
{
return "B!";
}
}
// Purposely placed here.
B.prototype = new A();
function SuperA()
{
SuperA.prototype.getSuperA = function()
{
return "SUPER A!";
}
}
A.prototype = new SuperA();
var objectB = new B();
alert(objectB.getA()); // A!
alert(objectB.getB()); // B!
alert(objectB.getSuperA()); // Error...
为什么允许更改遗产结构,即使是在使用中?这种继承结构的变化应该不会反映吧?
这是 3 种类型之间可能的/所谓的继承。当然,正确的做法是改变语句 "B.prototype = new A();" 的位置,但我是故意离开的。
那是因为你不能声明继承结构。所有继承都是在运行时动态完成的,因此没有时间点无法再更改它。
当您使用一个 class 的实例作为另一个的原型时,它是在继承该实例,而不仅仅是复制结构。示例:
function A() {}
A.prototype = {
hello: function() {}
};
var a = new A();
function B() {}
B.prototype = a;
var b = new B();
// all instances of B has the hello method
b.hello();
// add a method to the A instance
a.goodbye = function() {};
// now all instances of B have that method
b.goodbye();
这一行:
B.prototype = new A();
说将原型分配给 A 的一个实例。
如果省略构造函数调用,则相当于:
B.prototype = Object.create(A.prototype);
这意味着 B.prototype
指向从 A.prototype
克隆的对象:
Object.getPrototypeOf(B.prototype) === A.prototype // true
但是在这一行中:
A.prototype = new SuperA();
您正在替换 A.prototype
中的引用,但 B.prototype
仍然指向旧引用:
var oldProto = A.prototype;
A.prototype = new SuperA();
Object.getPrototypeOf(B.prototype) === A.prototype // false
Object.getPrototypeOf(B.prototype) === oldProto // true
这一行有效:
alert(objectB.getA());
因为 getA
是在 new A()
调用中添加的,所以它向现有原型添加了一个新插槽,而不是替换整个实例。
还有这个:
alert(objectB.getSuperA());
不起作用,因为 SuperA 不在 B 的原型链中。
这个问题很棘手。但实际上 JavaScript 有一个非常简单的模型,但被一些语言关键字(new/instanceof)和函数的奇怪使用(类似于 Java 构造函数)混淆了:
- Property/method 查找总是在原型链中向上。这就是你所有的遗产。
- "Clonning"(就Object.create而言)意味着创建一个新的空对象,并从给定的对象设置原型。
- 原型只是对对象的引用,因此您可以随时 add/change 插槽。
只有这两件事你不需要其余的。和构造函数 - 有一些小的内部差异 - 可以看作是一个捷径:
var newInstance = Object.create(SomeFunction.prototype);
SomeFunction.constructor.apply(newInstance, arguments);
对我来说,使用函数创建对象是个坏主意,如果 JavaScript 只有版本 1 中的 Object.create
而没有构造函数,那么所有模型都更容易理解。
谁能告诉我,为什么允许这样做(?):
function A()
{
A.prototype.getA = function()
{
return "A!";
}
}
function B()
{
B.prototype.getB = function()
{
return "B!";
}
}
// Purposely placed here.
B.prototype = new A();
function SuperA()
{
SuperA.prototype.getSuperA = function()
{
return "SUPER A!";
}
}
A.prototype = new SuperA();
var objectB = new B();
alert(objectB.getA()); // A!
alert(objectB.getB()); // B!
alert(objectB.getSuperA()); // Error...
为什么允许更改遗产结构,即使是在使用中?这种继承结构的变化应该不会反映吧?
这是 3 种类型之间可能的/所谓的继承。当然,正确的做法是改变语句 "B.prototype = new A();" 的位置,但我是故意离开的。
那是因为你不能声明继承结构。所有继承都是在运行时动态完成的,因此没有时间点无法再更改它。
当您使用一个 class 的实例作为另一个的原型时,它是在继承该实例,而不仅仅是复制结构。示例:
function A() {}
A.prototype = {
hello: function() {}
};
var a = new A();
function B() {}
B.prototype = a;
var b = new B();
// all instances of B has the hello method
b.hello();
// add a method to the A instance
a.goodbye = function() {};
// now all instances of B have that method
b.goodbye();
这一行:
B.prototype = new A();
说将原型分配给 A 的一个实例。 如果省略构造函数调用,则相当于:
B.prototype = Object.create(A.prototype);
这意味着 B.prototype
指向从 A.prototype
克隆的对象:
Object.getPrototypeOf(B.prototype) === A.prototype // true
但是在这一行中:
A.prototype = new SuperA();
您正在替换 A.prototype
中的引用,但 B.prototype
仍然指向旧引用:
var oldProto = A.prototype;
A.prototype = new SuperA();
Object.getPrototypeOf(B.prototype) === A.prototype // false
Object.getPrototypeOf(B.prototype) === oldProto // true
这一行有效:
alert(objectB.getA());
因为 getA
是在 new A()
调用中添加的,所以它向现有原型添加了一个新插槽,而不是替换整个实例。
还有这个:
alert(objectB.getSuperA());
不起作用,因为 SuperA 不在 B 的原型链中。
这个问题很棘手。但实际上 JavaScript 有一个非常简单的模型,但被一些语言关键字(new/instanceof)和函数的奇怪使用(类似于 Java 构造函数)混淆了:
- Property/method 查找总是在原型链中向上。这就是你所有的遗产。
- "Clonning"(就Object.create而言)意味着创建一个新的空对象,并从给定的对象设置原型。
- 原型只是对对象的引用,因此您可以随时 add/change 插槽。
只有这两件事你不需要其余的。和构造函数 - 有一些小的内部差异 - 可以看作是一个捷径:
var newInstance = Object.create(SomeFunction.prototype);
SomeFunction.constructor.apply(newInstance, arguments);
对我来说,使用函数创建对象是个坏主意,如果 JavaScript 只有版本 1 中的 Object.create
而没有构造函数,那么所有模型都更容易理解。