__proto__ VS。JavaScript 中的原型

IT技术 javascript prototype javascript-objects prototypal-inheritance
2021-01-13 23:06:50

该图再次表明每个对象都有一个原型。构造函数 Foo 也有它自己__proto__的 Function.prototype,它反过来也通过它的__proto__属性再次引用Object.prototype。因此,重复一遍,Foo.prototype 只是 Foo 的一个显式属性,它指的是 b 和 c 对象的原型。

var b = new Foo(20);
var c = new Foo(30);

__proto__之间有什么区别prototype

在此处输入图片说明

该图取自dmitrysoshnikov.com

注意:以上 2010 年的文章现在有第二版(2017 年)

6个回答

__proto__是在查找链中用于解析方法等的实际对象。 prototype__proto__在您创建对象时用于构建的对象new

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
__proto__对象属性是指向对象的构造函数的prototype属性的指针是否公平即 foo.__proto__ === foo.constructor.prototype
2021-03-11 23:06:50
啊! Soprototype不适用于实例本身(或其他对象),而仅适用于构造函数。
2021-03-25 23:06:50
@rvighne:prototype仅适用于函数,因为它们派生自Function, FunctionObject但在其他任何情况下都不是。不过,__proto__随处可见。
2021-03-29 23:06:50
@Alex_Nabu 不完全是。newCar.__proto__ IS Car.prototype,不是 的实例Car.prototype虽然Car.protoype 一个object. Car.prototype是不是,让newCar任何属性或结构,它只是IS在未来objectnewCar的原型链。Car.prototype不是暂时的object它被object设置为使用as a 创建__proto__的任何 new objects属性如果您想将任何事物视为蓝图请将其视为新车的蓝图CarconstructorobjectCarobject
2021-03-29 23:06:50
因此,__proto__是保存和使用为原型而实际的对象Myconstructure.prototype,不过是为了蓝图 __proto__这是逸岸保存和使用作为protoype实际的对象。因此myobject.prototype不会是实际对象的属性,因为它只是构造函数用来概述myobject.__proto__应该是什么样子的临时事物
2021-03-31 23:06:50

prototype是 Function 对象的属性。它是由该函数构造的对象的原型。

__proto__是一个对象的内部属性,指向它的原型。当前标准提供了一种等效的Object.getPrototypeOf(obj)方法,尽管事实上的标准__proto__更快。

您可以instanceof通过将函数prototype与对象__proto__进行比较来找到关系,并且可以通过更改prototype.

function Point(x, y) {
    this.x = x;
    this.y = y;
}

var myPoint = new Point();

// the following are all true
myPoint.__proto__ == Point.prototype
myPoint.__proto__.__proto__ == Object.prototype
myPoint instanceof Point;
myPoint instanceof Object;

Point是一个构造函数,它按程序构建一个对象(数据结构)。myPoint是一个由Point()so构造的对象,当时Point.prototype保存到myPoint.__proto__

此外,如果您更改__proto__对象属性,则会更改进行原型查找的对象。例如,您可以将方法对象添加为函数__proto__以拥有某种可调用的实例对象。
2021-03-10 23:06:50
myPoint.__proto__.constructor.prototype == Point.prototype
2021-04-01 23:06:50
我想我明白了你的观点。
2021-04-02 23:06:50
@kzh 大声笑给了我有趣的结果console.log(obj1.call) // [Function: call] obj1.call()// TypeError: obj1.call is not a function。我做了obj.__proto__ = Function.__proto__
2021-04-03 23:06:50
myFn.__proto__ = {foo: 'bar'}
2021-04-06 23:06:50

prototype 属性是在声明函数时创建的。

例如:

 function Person(dob){
    this.dob = dob
 }; 

Person.prototype一旦你声明了上面的函数,属性就会在内部创建。许多属性可以添加到Person.prototypePerson使用创建实例共享的new Person().

// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob}; 

值得注意的Person.prototypeObject,默认情况下是一个文字(可以根据需要更改)。

使用创建的每个实例new Person()都有一个__proto__指向Person.prototype. 这是用于遍历以查找特定对象的属性的链。

var person1 = new Person(somedate);
var person2 = new Person(somedate);

创建 2 个实例Person,这 2 个对象可以调用as 、 的age方法Person.prototypeperson1.ageperson2.age

在您的问题的上图中,您可以看到它Foo是 a Function Object,因此它有一个__proto__指向 的链接,而Function.prototype后者又是 的一个实例Object并具有__proto__指向 的链接Object.prototypeproto 链接在此处结束__proto__Object.prototype指向null.

任何对象都可以访问其原型链中由 链接的所有属性__proto__,从而形成原型继承的基础。

__proto__不是访问原型链的标准方法,标准但类似的方法是使用Object.getPrototypeOf(obj).

下面的instanceof运算符代码可以更好地理解:

当对象是类的实例时,对象instanceof类运算符返回true,更具体地说,如果Class.prototype在该对象的原型链中找到,则该对象是该类的实例。

function instanceOf(Func){
  var obj = this;
  while(obj !== null){
    if(Object.getPrototypeOf(obj) === Func.prototype)
      return true;
    obj = Object.getPrototypeOf(obj);
  }
  return false;
}      

上面的方法可以称为:instanceOf.call(object, Class)如果对象是类的实例,则返回true。

我想知道为什么prototype首先在内部创建对象?可以简单地将静态方法分配给函数对象本身。例如function f(a){this.a = a}; f.increment = function(){return ++this.a}为什么不选择这种方式而不是将方法添加到prototype对象?如果f.__proto__ = gg 是基类,这将起作用
2021-03-17 23:06:50
@abhisekp 你是什么意思:“如果 f.__proto__ = g 其中 g 是基类,这将起作用。” 我不知道这是否有我不明白的含义,但是如果您以这种方式添加属性和方法,那么当您使用new关键字创建实例时,不会复制属性和方法超过。
2021-03-25 23:06:50
也许prototype选择共享对象是因为只有独占的函数构造函数属性可以存储在函数构造函数对象中。
2021-03-27 23:06:50
事实上,这将是一个烂摊子,因为instanceof会导致({}) instanceof Function === true如就没有办法,如果原型之间进行区分prototype财产被删除。
2021-04-05 23:06:50

为了解释让我们创建一个函数

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

当 JavaScript 执行这段代码时,它会添加prototypeproperty 到aprototypeproperty 是一个有两个属性的对象:

  1. constructor
  2. __proto__

所以当我们做

a.prototype 它返回

     constructor: a  // function definition
    __proto__: Object

现在正如你所看到的constructor,只是函数a本身并__proto__指向ObjectJavaScript的根级别

让我们看看当我们使用a带有new关键字的函数时会发生什么

var b = new a ('JavaScript');

当 JavaScript 执行这段代码时,它会做 4 件事:

  1. 它创建一个新对象,一个空对象 // {}
  2. 它创建__proto__b并使其指向a.prototype这样b.__proto__ === a.prototype
  3. 使用新创建的对象(在步骤#1 中创建)作为其上下文(this)执行a.prototype.constructor(这是 function 的定义a),因此name作为“JavaScript”(添加到this传递属性被添加到新创建的对象中。
  4. 它返回新创建的对象(在步骤#1 中创建),因此 varb被分配给新创建的对象。

现在,如果我们添加a.prototype.car = "BMW"并执行 b.car,就会出现输出“BMW”。

这是因为当 JavaScript 执行这段代码时,它搜索了car属性 on b,它没有找到然后使用的 JavaScript b.__proto__(它在步骤#2 中指向'a.prototype')并找到car属性所以返回“BMW”。

1.constructor不退a()它返回a2.__proto__返回Object.prototype,而不是 Javascript 中的根对象。
2021-03-12 23:06:50
这是一个很好的答案!
2021-03-28 23:06:50
+1这是解释原型实际上是什么(具有两个属性的对象)以及Javascript如何执行每段代码的最佳答案。这个信息出乎意料地难以获得。
2021-03-29 23:06:50

一个很好的思考方式是......

prototypeconstructor函数使用。它真的应该被称为类似的东西"prototypeToInstall",因为它就是这样。

并且__proto__是对象上的“安装原型”(从所述constructor()函数创建/安装在对象上

请将“ constructor()functions”更改为“constructor functions”,因为可能会与“ __proto__.constructor()functions”混淆我认为这很重要,因为在使用new关键字时实际上不会调用 __proto__.constructor
2021-03-10 23:06:50
构造函数() 函数使用原型”这一说法只说明了一个重要事实的一部分,但以一种可能会让读者认为这是全部事实的方式告诉它。原型是为 JavaScript 中的每个函数声明在内部创建的,无论将来如何调用该函数 - 使用或不使用new关键字;声明函数的原型指向对象字面量。
2021-03-11 23:06:50
我赞成它,但也许反对的原因是因为声明“构造函数()函数使用原型”听起来好像非构造函数没有,事实并非如此,但除此之外,它现在也不是我们的重点可以注意到,如果使用 new 调用,每个函数都可能是一个构造函数...
2021-04-04 23:06:50