美文网首页
__proto__, [[prototype]] , proto

__proto__, [[prototype]] , proto

作者: 魂斗驴 | 来源:发表于2021-02-07 12:31 被阅读0次

原型是构造函数上的属性,该函数设置将成为构造对象的proto属性。

每个对象都可以有另一个对象作为其原型。然后,前一个对象继承了其所有原型的属性。对象通过内部属性指定其原型[[Prototype]]。通过[[Prototype]]属性连接的对象链称为原型链:

Prototype

为了了解基于原型的继承(或原型)的继承方式,让我们看一个示例(使用用于指定[[Prototype]]属性的发明语法):

var proto = {
    describe: function () {
        return 'name: '+this.name;
    }
};
var obj = {
    [[Prototype]]: proto,
    name: 'obj'
};
> obj.describe
[Function]
> obj.describe()
'name: obj'

__proto__是一个存取器属性的的Object.prototype对象。它公开了内部原型链接[[Prototype]])

function Foo(name) {
  this.name = name;
}

var b = new Foo('b');
var a = new Foo('a');
b.say = function() {
  console.log('Hi from ' + this.whoAmI());
}
console.log(a.__proto__ === Foo.prototype); // true
console.log(a.__proto__ === b.__proto__); // true
prototype

JavaScript引擎将say()方法添加到b对象,而不是Foo.prototype对象。

如您在图中所看到的,a.proto暴露了[[Prototype]]指向Foo.prototype对象的。同样,b.proto也指向与a.proto

示例1:通过构造函数创建对象

除了通过指定的模式创建对象外,构造函数还可以做另一件事-它会自动为新创建的对象设置prototype。该prototype存储在ConstructorFunction.prototype属性中。

例如在之前示例中, 我们可以用构造函数重写带有对象b.

function Foo(y) {
  this.y = y;
}

Foo.prototype.x = 10;
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};

var b = new Foo(20);
b.calculate(30); // 60
console.log(
  b.__proto__ === Foo.prototype, // true
  b.__proto__.calculate === Foo.prototype.calculate // true
  b.__proto__.calculate === b.calculate, // true
  Foo === b.constructor, // true
  Foo === Foo.prototype.constructor, // true
);

如上所示,b是从Foo()继承的方法。“ Foo.prototype”自动创建一个特殊属性“ constructor”,该属性是对构造函数本身的引用。
实例“ b”可以通过委托找到它,并用于检查其构造函数。

prototype

示例2:JavaScript经典继承图

这是一个关于通过构造函数创建对象的示例,但是我们将重点放在这些对象和实例系列期间的原型链问题。原型对象也只是简单的对象,可能有自己的原型。如果某个原型对其原型具有非空引用,依此类推,则称为原型链

原型链png

现在,从图中可以看出为什么当我们从Animal继承Dog时,我们会这样做:

function Dog() {} // the usual constructor function
 Dog.prototype = new Animal();
 Dog.prototype.constructor = Dog;

当new()一个实例时会发生什么:

需要注意的是,原型在Foo.prototype是不是形成一个原型链。Foo.prototype 指向原型链中的某些位置,但是Foo的原型属性不是构成原型链。什么构成了一个原型链是proto朝上链,且对象指向proto,如去富.__ proto__,马上要到富..__ proto__,依此类推,直到空为止。

proto和原型的关系

JavaScript的工作方式如下:我是一个构造函数,我只是一个函数,并且我拥有一个原型引用,并且每当调用foo = new Foo()时,我都会让foo .__ proto__指向我的原型对象。因此,Foo.prototype和obj .__ proto__是两个不同的概念。Foo.prototype指示创建Foo的对象时,这是新对象的原型链应指向的位置,即foo .__ proto__应指向Foo.prototype指向的位置。

如果需要添加功能怎么办?

如果woofie对象没有move方法,它将像任何原型继承场景一样,沿着原型链上升,首先到达woofie .__ proto__指向的对象,这与Dog.prototype引用的对象相同至。如果方法move不是该对象的属性(意味着Dog类没有方法move),请在原型链中上一层,即woofie .__ proto . proto__,或与Animal.prototype相同。

Animal.prototype.move = function() { ... };
__proto__

即使foo.constructor === Foo,构造方法属性也不是foo自己的属性。它实际上是通过向上访问foo .__ proto__所指向的原型链来获得的。这同样适用于Function.constructor。当我们看到Constructor.prototype,foo .__ proto__,Foo.prototype.constructor时,该图可能很复杂,有时会造成混淆。

为了验证该图,请注意,即使foo.constructor将显示一个值,该属性构造函数也不是foo的自己的属性,而是通过跟踪原型链来获得的,如foo.hasOwnProperty(“ constructor”)所示。

笔记:

**[[Prototype]]**对象通过内部属性指定其原型

**__proto__**直接访问[[Prototype]]

**prototype**是的对象是用于构建__proto__,当你创建一个对象new.

**prototype** 在实例本身(或其他对象)上不可用,而仅在构造函数上可用。

**prototype**仅在函数上可用,因为它们是从中复制的FunctionObject,而在其他任何函数中则不是。但是,**__proto__**随处可见。

( new Foo ).__proto__ === Foo.prototype  //true
( new Foo ).prototype === undefined      //true

委托原型和串联继承

Cat.prototype = new Animal();
//它将通过继承层次结构正确遵循原型链。

Cat.prototype = Animal.prototype
//Cat原型的任何运行时更改也会影响动物

原型上不存在静态属性/功能。在prototype一个时才使用new被创建的实例。

喜欢这个故事吗?对别人有帮助吗?轻按下面的心脏,它可以帮助我知道您是否想写更多有关他的话题的信息,并帮助人们看到故事。

参考

Javascript inheritance behind the scene proto, [[prototype]] and prototype

相关文章

网友评论

      本文标题:__proto__, [[prototype]] , proto

      本文链接:https://www.haomeiwen.com/subject/chkotltx.html