__proto__ VS. JavaScript中的原型

问题描述 投票:704回答:25

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

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

__proto__prototype属性有什么区别?

该图取自here

javascript prototype javascript-objects prototypal-inheritance
25个回答
689
投票

__proto__是在查找链中用于解析方法等的实际对象.prototype是在使用__proto__创建对象时用于构建new的对象:

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;

6
投票

理解它的另一个好方法:

__proto__

仅在支持IE11 constructor之后。在该版本之前,例如IE9,您可以使用__proto__来获取__proto__


5
投票

原型

prototype是Function的一个属性。它是使用带有new关键字的(构造函数)函数创建对象的蓝图。

__proto__

__proto__用于查找链以解析方法,属性。创建对象时(使用带有new关键字的构造函数),function Robot(name) { this.name = name; } var robot = new Robot(); // the following are true robot.__proto__ == Robot.prototype robot.__proto__.__proto__ == Object.prototype 设置为(Constructor)Function.prototype

prototype

这是我(假想的)解释清除混乱:

想象一下,有一个与功能相关的想象类(蓝图/ coockie切割器)。该虚构类用于实例化对象。 function Robot(name) { this.name = name; } 是扩展机制(C#中的扩展方法,或Swift扩展),用于向该虚构类添加内容。

// imaginary class
class Robot extends Object{

    static prototype = Robot.class  
    // Robot.prototype is the way to add things to Robot class
    // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype

    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

} 

以上可以想象为:

var robot = new Robot();

robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype

所以,

prototype

现在添加方法到机器人的Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y}; // Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)

// Swift way of extention
extension Robot{
    function move(x, y){    
        Robot.position.x = x; Robot.position.y = y
    }
}

以上可以想象为Robot类的扩展:

// imaginary class
class Robot{

    static prototype = Robot.class // Robot.prototype way to extend Robot class
    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

    // added by prototype (as like C# extension method)
    function move(x, y){ 
        Robot.position.x = x; Robot.position.y = y
    };
}

反过来,

> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true

4
投票

简而言之:

 JavaScript prototype vs __prototype__ 

这允许您将属性附加到X.prototype AFTER类型的对象已被实例化,并且他们仍然可以通过__proto__引用访问这些新属性,Javascript引擎用它来走原型链。


4
投票

'use strict' function A() {} var a = new A(); class B extends A {} var b = new B(); console.log('====='); // ===== console.log(B.__proto__ === A); // true console.log(B.prototype.__proto__ === A.prototype); // true console.log(b.__proto__ === B.prototype); // true console.log(a.__proto__ === A.prototype); // true console.log(A.__proto__ === Function.__proto__); // true console.log(Object.__proto__ === Function.__proto__); // true console.log(Object.prototype === Function.__proto__.__proto__); // true console.log(Object.prototype.__proto__ === null); // true

__proto__

在JavaScript中,每个对象(函数也是对象!)都有一个new属性,该属性是对其原型的引用。

当我们使用__proto__运算符和构造函数来创建一个新对象时,新对象的prototype属性将使用构造函数的__proto__属性进行设置,然后构造函数将被新对象调用,在该过程中“this”将是对构造函数作用域中的新对象,最后返回新对象。

构造函数的原型是prototype属性,Constructor的new属性与prototype运算符一起使用。

构造函数必须是一个函数,但即使函数具有__proto__属性,函数也不总是构造函数。

原型链实际上是对象的__proto__属性来引用它的原型,而原型的__proto__属性引用原型的原型,依此类推,直到引用Object的原型的console.log(a.constructor === A); // true // "a" don't have constructor, // so it reference to A.prototype by its ``__proto__`` property, // and found constructor is reference to A 属性,它引用了null。

例如:

[[Prototype]]

__proto__console.log(Object.getPrototypeOf(a) === a.__proto__); // true 财产实际上是一回事。

我们可以使用Object的getPrototypeOf方法来获取原型。

new

我们编写的任何函数都可以用于使用https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype运算符创建对象,因此这些函数中的任何一个都可以是构造函数。


3
投票

Prototype或Object.prototype是对象文字的属性。它表示Object原型对象,您可以覆盖它以在原型链中进一步添加更多属性或方法。

__proto__是一个访问器属性(get和set函数),它公开了访问它的对象的内部原型。

参考文献:

  1. http://www.w3schools.com/js/js_object_prototypes.asp
  2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
  3. function Foo(message){ this.message = message ; }; console.log(Foo.prototype);

3
投票

我知道,我迟到但让我试着简化它。

让我们说有一个功能

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);

Foo函数将链接原型对象。因此,每当我们在JavaScript中创建一个函数时,它总是有一个链接到它的原型对象。

现在让我们继续使用函数Foo创建两个对象。

    b.__proto__ === Object.getPrototypeOf(a);
    a.__proto__ ===  Foo.prototype;
    a.constructor.prototype  === a.__proto__;
  1. 现在我们有两个对象,对象a和对象b。两者都是使用构造函数Foo创建的。请记住构造函数在这里只是一个词。
  2. 对象a和b都有一个消息属性的副本。
  3. 这两个对象a和b链接到构造函数Foo的原型对象。
  4. 在对象a和b上,我们可以在所有浏览器中使用proto属性访问Foo原型,在IE中我们可以使用Object.getPrototypeOf(a)或Object.getPrototypeOf(b)

现在,Foo.prototype,a.proto和b.proto都表示相同的对象。

    Foo.prototype.Greet = function(){

         console.log(this.message);
    }
    a.Greet();//a
    b.Greet();//b
    a.constructor.prototype.Greet();//undefined 

以上所有都将返回true。

众所周知,JavaScript属性可以动态添加。我们可以添加属性到对象

__proto__

如您所见,我们在Foo.prototype中添加了Greet()方法,但它可以在a和b或使用Foo构造的任何其他对象中访问。

在执行a.Greet()时,JavaScript将首先在对象a属性列表中搜索Greet。如果没有找到,它将会进入原型链。由于a.proto和Foo.prototype是同一个对象,JavaScript会找到Greet()方法并执行它。

我希望,现在原型和proto有点简化了。


3
投票

摘要:

对象的prototype属性是映射到对象的构造函数的instance.__proto__ === constructor.prototype // true的属性。换一种说法:

prototype

这用于形成对象的prototype链。 protochain链是对象属性的查找机制。如果访问了对象的属性,JavaScript将首先查看对象本身。如果在那里找不到该属性,它将一直爬到function Person (name, city) { this.name = name; } Person.prototype.age = 25; const willem = new Person('Willem'); console.log(willem.__proto__ === Person.prototype); // the __proto__ property on the instance refers to the prototype of the constructor console.log(willem.age); // 25 doesn't find it at willem object but is present at prototype console.log(willem.__proto__.age); // now we are directly accessing the prototype of the Person function 直到找到(或不找到)

例:

true

我们的第一个日志结果是__proto__,这是因为如前所述,构造函数创建的实例的prototype属性引用了构造函数的__proto__属性。请记住,在JavaScript中,函数也是对象。对象可以具有属性,任何函数的默认属性都是名为prototype的一个属性。

然后,当此函数用作构造函数时,从其实例化的对象将接收名为__proto__的属性。而这个prototype属性指的是构造函数的Objects属性(默认情况下每个函数都有)。

为什么这有用?

在查找__proto__上的属性时,JavaScript有一种机制,称为“原型继承”,这里它基本上是这样做的:

  • 首先,检查属性是否位于Object本身。如果是,则返回此属性。
  • 如果属性不在对象本身上,它将“爬上原始链接”。它基本上是查看__proto__属性引用的对象。在那里,它检查__proto__引用的对象上的属性是否可用。
  • 如果该属性不在__proto__对象上,它将爬上Object链,一直到prototype对象。
  • 如果它无法在对象及其undefined链上的任何位置找到该属性,它将返回function Person (name) { this.name = name; } let mySelf = new Person('Willem'); console.log(mySelf.__proto__ === Person.prototype); console.log(mySelf.__proto__.__proto__ === Object.prototype);

例如:

prototype

2
投票

DEFINITIONS

(括号()内的数字是下面写的代码的“链接”)

ConstructorFunction.prototype - 包含以下内容的对象: =>这个特定的__proto__(5)的函数(3),每个通过这个构造函数创建或创建的对象(4)都可以访问它们(1) =>构造函数本身(1) =>此特定对象的__proto__(原型对象)

__proto__(dandor proto?) - 通过特定构造函数(1)创建的任何对象(2)的链接,以及该构造函数的原型对象属性(5)允许每个创建的对象(2)访问原型的函数和方法(4)( function Person (name, age) { this.name = name; this.age = age; 
 } 默认包含在JS中的每个对象中)

CODE CLARIFICATION

1.

    var John = new Person(‘John’, 37);
    // John is an object

2.

    Person.prototype.getOlder = function() {
        this.age++;
    }
    // getOlder is a key that has a value of the function

3.

    John.getOlder();

4.

    Person.prototype;

5.

prototype

1
投票

我会尝试四年级的解释:

事情很简单。 function是应该如何构建某个东西的一个例子。所以:

  • 我是一个prototype,我建立类似于我的object的新对象
  • 我是__proto__,我是以我的function Foo() { } var bar = new Foo() // `bar` is constructed from how Foo knows to construct objects bar.__proto__ === Foo.prototype // => true // bar is an instance - it does not know how to create objects bar.prototype // => undefined 为例建造的

证明:

prototype

1
投票

您创建的每个函数都有一个名为__proto__的属性,它作为一个空对象开始。在将此函数用作构造函数(即使用'new'关键字)之前,此属性无用。

这经常与对象的prototype属性混淆。有些人可能会感到困惑,除了对象的prototype属性可能会使它们成为对象的原型。但事实并非如此。 __proto__用于获取从函数构造函数创建的对象的function Person(name){ this.name = name }; var eve = new Person("Eve"); console.log(eve.__proto__ == Person.prototype) // true // this is exactly what prototype does, made Person.prototype equal to eve.__proto__

在上面的例子中:

(function(){ 
      let a = function(){console.log(this.b)};
      a.prototype.b = 1;
      a.__proto__.b = 2;
      let q = new a();
      console.log(a.b);
      console.log(q.b) 
    })()

我希望这是有道理的。


310
投票

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

__proto__是一个对象的内部属性,指向它的原型。目前的标准提供了一个等效的Object.getPrototypeOf(O)方法,虽然事实上的标准__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()建造的一个物体,所以Point.prototype当时被保存到myPoint.__proto__


1
投票

__proto__

试试这段代码吧


1
投票

prototype是构造function human(){}和构造函数的基础,例如:prototype__proto__,它在构造函数的新实例中通过here共享。更详细的阅读function Dog(){} Dog.prototype.bark = "woof" let myPuppie = new Dog()


1
投票

解释性的例子:

__proto__

现在,myPupppie有> myPuppie.__proto__ >> {bark: "woof", constructor: ƒ} 属性,指向Dog.prototype。

> myPuppie.prototype
>> undefined

但myPuppie没有原型属性。

__proto__

因此,mypuppie的__proto__是对构造函数的.prototype属性的引用,该属性用于实例化此对象(并且当前的myPuppie对象具有与此proto vs prototype - Object Creation in JavaScript对象的“委托”关系),而myPuppie的.prototype属性根本不存在(因为我们没有设置它)。

MPJ在这里给出了很好的解释:__proto__


0
投票

使用function Foo(name){ this.name = name Foo.__proto__.collection.push(this) Foo.__proto__.count++ } Foo.__proto__.count=0 Foo.__proto__.collection=[] var bar = new Foo('bar') var baz = new Foo('baz') Foo.count;//2 Foo.collection // [{...}, {...}] bar.count // undefined 静态方法怎么样?

var q = {}
var prototype = {prop: 11}

q.prop // undefined
q.__proto__ = prototype
q.prop // 11

-1
投票

我的理解是:__ proto__和原型都是为原型链技术服务的。不同之处在于使用下划线命名的函数(如__proto__)并不是开发人员明确调用的目标。换句话说,它们只是用于继承等机制,它们是“后端”。但是没有下划线命名的函数是为明确调用而设计的,它们是'前端'。


-3
投票

!!!这是世界上最好的解释!!!!!

q.__proto__ = prototype

在函数构造函数javascript引擎当我们写new Class时自动调用这个__proto__,并且在Class.prototype prop set function Class(){} Class.prototype = {prop: 999} // set prototype as we need, before call new var q = new Class() // q.__proto__ = Class.prototype q.prop // 999

qazxswpoi

请享用 %)


109
投票

声明函数时会创建Prototype属性。

例如:

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

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

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

值得注意的是,Person.prototype默认是Object文字(可以根据需要进行更改)。

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

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

创建Person的2个实例,这2个对象可以将agePerson.prototype方法称为person1.ageperson2.age

在你问题的上图中,你可以看到Foo是一个Function Object,因此它有一个__proto__链接到Function.prototype,而Object又是__proto__的一个实例,并且有Object.prototype链接到__proto__。原型链接在Object.prototype指向null__proto__结束。

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

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

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

object true当一个对象是一个Class的实例时,类运算符返回Class.prototype,更具体地说,如果在该对象的proto链中找到function instanceOf(Func){ var obj = this; while(obj !== null){ if(Object.getPrototypeOf(obj) === Func.prototype) return true; obj = Object.getPrototypeOf(obj); } return false; } ,那么该对象就是该Class的一个实例。

instanceOf.call(object, Class)

上面的方法可以称为:prototype,如果object是Class的实例,则返回true。


61
投票

想到它的好方法是......

constructor()"prototypeToInstall"函数使用。它应该被称为像__proto__这样的东西,因为它就是它的本质。

constructor()是一个对象的“安装原型”(从所述 function a (name) { this.name = name; } 函数创建/安装在对象上)


45
投票

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

prototype

当JavaScript执行此代码时,它会将a属性添加到prototypeconstructor属性是一个具有两个属性的对象:

  1. __proto__
  2. a.prototype

所以,当我们这样做

constructor: a // function definition __proto__: Object 它返回

constructor

现在你可以看到a只是功能__proto__本身和Object指向JavaScript的根级别a

让我们看看当我们使用new函数和var b = new a ('JavaScript'); 关键词时会发生什么。

__proto__

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

  1. 它创建一个新对象,一个空对象// {}
  2. 它在b创建a.prototype并使其指向b.__proto__ === a.prototype所以a.prototype.constructor
  3. 它使用新创建的对象(在步骤#1中创建)作为其上下文(this)执行a(函数name的定义),因此作为'JavaScript'传递的this属性(添加到b)被添加到新的创建对象。
  4. 它返回新创建的对象(在步骤#1中创建),因此var a.prototype.car = "BMW"被分配给新创建的对象。

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

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


44
投票

constructor

在创建函数时,会自动创建一个名为prototype的属性对象(您自己没有创建它)并且正在附加到函数对象(function Foo () { this.name = 'John Doe'; } // Foo has an object property called prototype. // prototype was created automatically when we declared the function Foo. Foo.hasOwnProperty('prototype'); // true // Now, we can assign properties and methods to it: Foo.prototype.myName = function () { return 'My name is ' + this.name; } )。 注意:这个新的原型对象也指向或具有本机JavaScript对象的内部私有链接。

例:

Foo

如果你将使用new关键字从Foo创建一个新对象,你基本上创建(除其他外)一个新对象,它具有我们前面讨论过的函数原型var b = new Foo(); b.[[Prototype]] === Foo.prototype // true 的内部或私有链接:

[[Prototype]]


The private linkage to that function's object called double brackets prototype or just __proto__. Many browsers are providing us a public linkage to it that called __proto__!

更具体地说,getter function实际上是属于本机JavaScript对象的this。它返回[[Prototype]]绑定的内部 - 私有原型链接(返回bb.__proto__ === Foo.prototype // true ):

ECMAScript5

值得注意的是,启动getPrototypeOf,您还可以使用Object.getPrototypeOf(b) === b.__proto__ // true 方法获取内部私有链接:

__proto__


NOTE: this answer doesn't intend to cover the whole process of creating new objects or new constructors, but to help better understand what is prototype, [[Prototype]] and function Person(name){ this.name = name }; var eve = new Person("Eve"); eve.__proto__ == Person.prototype //true eve.prototype //undefined and how it works.

28
投票

除了上面的答案之外,还要清楚一点:

Instances of a constructor function use __proto__ to access the prototype property of its constructor function.

实例有__proto__,类有原型。


10
投票

在JavaScript中,函数可以用作构造函数。这意味着我们可以使用new关键字从中创建对象。每个构造函数都带有一个与它们链接在一起的内置对象。这个内置对象称为原型。 prototype diagram

function Foo(){}

  1. 首先我们创建了一个构造函数:Foo。要清楚,Foo只是另一个功能。但我们可以使用new关键字从中创建一个对象。这就是我们称之为构造函数的原因
  2. 每个函数都有一个唯一的属性,称为prototype属性。因此,构造函数Foo.prototype有一个原型属性,指向它的原型,即function Foo(见图)。
  3. 构造函数本身就是一个函数,它是一个名为[[Function]]构造函数的系统构造函数的实例。所以我们可以说__proto__是由[[Function]]构造函数构造的。因此,我们的Foo functionFunction.prototype将指向其构造函数的原型,即Function.prototype
  4. [[Object]]本身只不过是一个由另一个名为[[Object]]的系统构造函数构造的对象。因此,Function.prototypeFunction.prototype的构造者。所以,我们可以说[[Object]]__proto__的一个例子。所以Function.prototypeObject.prototype指向Object.prototype
  5. __proto__是站在原型链中的最后一个人。我的意思是它还没有建成。它已经存在于系统中。所以它的null指向Foo
  6. 现在我们来看看new Foo()的情况。当我们使用Foo创建一个实例时,它会创建一个新对象,它是Foo的一个实例。这意味着__proto__是这些实例的构造函数。这里我们创建了两个实例(x和y)。因此,x和y的Foo.prototype指向You Don't Know JS: this & Object Prototypes

7
投票

我碰巧从instanceof学习原型,这是一本很好的书,可以理解下面的设计并澄清如此多的误解(这就是为什么我试图避免使用继承和像[[Prototype]]这样的东西)。

但我有同样的问题,就像人们在这里问的那样。几个答案真的很有帮助和启发。我也很想分享我的理解。


What is a prototype?

JavaScript中的对象具有内部属性,在规范asnull中表示,它只是对另一个对象的引用。在创建它们时,几乎所有对象都被赋予了这个属性的非__proto__value。

How to get an object's prototype?

通过Object.getPrototypeOfor var a = { name: "wendi" }; a.__proto__ === Object.prototype // true Object.getPrototypeOf(a) === Object.prototype // true function Foo() {}; var b = new Foo(); b.__proto__ === Foo.prototype b.__proto__.__proto__ === Object.prototype

prototype

What is the prototype ?

a是一个自动创建的对象,它是一个函数的特殊属性,用于建立委托(继承)链,即原型链。

当我们创建一个函数prototype时,a会自动创建为constructor上的一个特殊属性,并将函数代码保存为prototype上的function Foo() {}; Foo.prototype // Object {constructor: function} Foo.prototype.constructor === Foo // true

Array.prototype.forEach()

我很乐意将此属性视为存储函数对象的属性(包括方法)的位置。这也是为什么JS中的实用函数定义为Function.prototype.bind()Object.prototype.toString().{}.prototype // undefined; (function(){}).prototype // Object {constructor: function} // The example above shows object does not have the prototype property. // But we have Object.prototype, which implies an interesting fact that typeof Object === "function" var obj = new Object(); 的原因

为什么要强调函数的属性?

Arary

所以,FunctionObject__proto__are所有功能。我应该承认这会刷新我对JS的印象。我知道函数是JS中的一等公民,但它似乎是建立在函数之上的。

What's the difference between prototype and __proto__?

[[Prototype]]a参考适用于每个对象,以引用其prototypeproperty。

function Foo() {} var b = new Foo(); b.__proto__ === Foo.prototype // true Foo.__proto__ === Function.prototype // true Function.prototype.__proto__ === Object.prototype // true 是一个自动创建的对象,它是一个函数的特殊属性,用于存储函数对象的属性(包括方法)。

有了这两个,我们就可以在精神上绘制原型链。如下图所示:

var foo = {}

/* 
foo.constructor is Object, so foo.constructor.prototype is actually 
Object.prototype; Object.prototype in return is what foo.__proto__ links to. 
*/
console.log(foo.constructor.prototype === foo.__proto__);
// this proves what the above comment proclaims: Both statements evaluate to true.
console.log(foo.__proto__ === Object.prototype);
console.log(foo.constructor.prototype === Object.prototype);
© www.soinside.com 2019 - 2024. All rights reserved.