什么's与“;原型”;

What's the opposite of "prototype"?

本文关键字:原型 什么      更新时间:2023-11-14

考虑以下内容:

var o = {foo: 'bar'};
var p = Object.create(o);

如果op原型,那么p相对于o是什么?

我不知道对原型是另一个对象的对象的形式术语有任何广泛的共识,但IMHO术语派生对象是可以接受的。

原型继承的意义在于,一个对象继承自另一个对象,或者从另一个派生。在一些经典OO语言(如C++)中,您会听到派生类这一术语,因为类继承自其他类。因为继承是原型语言中对象之间的继承,所以我认为"派生对象"是有意义的。

注意:实际上,每个对象的原型都有对构造函数的引用。所以这是错误的,尽管关于不太直接的关系的观点成立。原型对象仍然可以交换,但原型实际上已连接到对象,并且可以直接使用__proto__Object.getPrototypeOf(instance)访问(proto不是标准的,因此object.getPrototypeOf更理想(如果可用))。

我认为最好考虑对象的构造函数是否有原型。将Object.create想象成一个如下所示的函数:

function objCreate(prototypeObject){
    var constructor = function(){};
    constructor.prototype = prototypeObject;
    return new constructor;
}

因此,在以下情况下:

var o = {foo: 'bar'};
var p = objCreate(o);

o被分配给p的构造函数的prototype属性。

现在看看这个:

alert(p.foo);//'bar'
p.constructor.prototype = { foo: 'foobiedoobie', bar: 'ubarfu' }
alert(p.foo);//'foobiedoobie' // and we could access bar if we wanted to

使用术语"派生的"或任何其他断言这两种类型之间直接关系的东西都会混淆实际发生的事情,因为你可以随时交换p构造函数的原型属性,追溯性地更改p构造函数的所有实例可用的所有属性。p不是从o.派生的。在我们更改它之前,o是备份对象,如果您调用p没有的属性,则会检查其属性。然后,如果备份对象没有它,JS调用对象会检查其构造函数的原型,依此类推。

这就是为什么我个人不喜欢Object.create或即将推出的新类语法。这一切都是一样的,但我们为了一个非常小的语法胜利而掩盖了实际发生的不必要的事情,这让我们自己很容易产生的语法变得更加模糊。

那么p相对于o是什么呢?

p是一个构造函数的实例,该构造函数恰好以o为其原型。

那里没有直接的关系。试图断言一个类只会让人们感到困惑,他们会错过它的实际工作方式有多强大。你不能在大多数语言中交换一个类,然后突然调用所有新继承的属性。你可以在JS中。这是因为与继承方案相比,它更像是一个备份对象链,用于检查未在实例上直接设置的属性。

p将位于o的原型链下方,o将位于p的原型链上方。当无法直接在实例上找到某个成员时,将使用原型链。JavaScript将只查找原型链,直到找到成员或返回undefined:https://stackoverflow.com/a/16063711/1641941

var o = {o:22}
var p = Object.create(o);
p.p = 33;
var q = Object.create(p);
console.log(q);
console.log(q.__proto__);
console.log(q.__proto__.__proto__);