__proto__ VS. protótipo em JavaScript


785

Esta figura mostra novamente que todo objeto tem um protótipo. A função de construtor Foo também possui a sua própria __proto__, Function.prototype, e que, por sua vez, também faz referência, por sua __proto__propriedade, novamente ao Object.prototype. Assim, repita, Foo.prototype é apenas uma propriedade explícita de Foo que se refere ao protótipo de objetos bec.

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

Quais são as diferenças entre __proto__e prototype?

insira a descrição da imagem aqui

A figura foi retirada de dmitrysoshnikov.com .



5
Eu acho que de cima para baixo ou de baixo para cima é uma questão de preferência. Na verdade, prefiro assim, para que eu possa traçar o diagrama até descobrir de onde vem alguma coisa.
quer

1
Eu gosto de como o JavaScript usa herança prototípica para resolver y.constructor para y .__ proto __. Construtor. Também gosto de como Object.prototype fica no topo da cadeia de herança prototípica com Object.prototype .__ proto__ definido como null. Também gosto de como o diagrama faz uma visualização conceitual de três colunas de como o programador considera os objetos como 1. instâncias, 2. construtores, 3. protótipos que construtores associam a essas instâncias quando instanciados por meio da nova palavra-chave.
John Sonderson

Diagrama faz sentido imediato depois de assistir algo como youtube.com/watch?v=_JJgSbuj5VI , btw
mlvljr

E agora, ao ler as respostas, sinto-me obrigado a realmente recomendar o vídeo acima, pois ele realmente tem uma explicação clara (e não-WTFy) do que está acontecendo :)
mlvljr

Respostas:


766

__proto__é o objeto real usado na cadeia de pesquisa para resolver métodos etc. prototypeé o objeto usado para criar __proto__quando você cria um objeto com new:

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

239
Ah! Portanto, prototypenão está disponível nas próprias instâncias (ou outros objetos), mas apenas nas funções do construtor.
precisa saber é

43
@rvighne: prototypesó está disponível em funções, uma vez que são derivadas Function, Functione, Objectmas em qualquer outra coisa que não é. No entanto, __proto__está disponível em qualquer lugar.
Tarik

19
O mesmo __proto__é o objeto real que é salvo e usado como protótipo, enquanto Myconstructure.prototypeé apenas um plano para o __proto__qual está representado o objeto real salvo e usado como protótipo. Portanto, myobject.prototypenão seria uma propriedade do objeto real, porque é apenas uma coisa temporária usada pela função construtora para descrever como myobject.__proto__deve ser.
Alex_Nabu

9
É justo dizer que a __proto__propriedade de um objeto é um ponteiro para a prototypepropriedade da função construtora do objeto ? ie foo .__ proto__ === foo.constructor.prototype
Niko Bellic

10
@Alex_Nabu Não é bem assim. newCar.__proto__ IS Car.prototype , não é uma instância de Car.prototype. Enquanto Car.protoype IS é uma instância de um object. Car.prototypenão é algo que fornece newCarpropriedades ou estrutura; simplesmente é o próximo objectna newCarcadeia de protótipos. Car.prototypenão é temporário object. É objecto valor definido como o valor da __proto__propriedade de qualquer novo objects feito usando Carcomo a constructor. Se você quiser pensar em algo como um plano object, pense Carem um plano para carros novos object.
Seangwright

336

prototypeé uma propriedade de um objeto Function. É o protótipo de objetos construídos por essa função.

__proto__é propriedade interna de um objeto, apontando para seu protótipo. Os padrões atuais fornecem um Object.getPrototypeOf(O)método equivalente , embora o padrão de fato__proto__ seja mais rápido.

Você pode encontrar instanceofrelacionamentos comparando uma função prototypecom a __proto__cadeia de um objeto e pode quebrá-los alterando 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;

Aqui Pointestá uma função construtora, ela cria um objeto (estrutura de dados) processualmente. myPointé um objeto construído por Point()assim Point.prototypefica guardado para myPoint.__proto__naquele momento.


2
Além disso, se você alterar a __proto__propriedade de um objeto, ele mudará o objeto no qual as pesquisas de protótipo são feitas. Por exemplo, você pode adicionar um objeto de métodos como uma função __proto__para ter um tipo de objeto de instância que pode ser chamado.
Kzh 19/08/2014

. myPoint .__ proto __ constructor.prototype == Point.prototype
Francisco

@kzh lol que me deu um resultado engraçado console.log(obj1.call) // [Function: call] obj1.call()// TypeError: obj1.call não é uma função. Eu fizobj.__proto__ = Function.__proto__
abhisekp

myFn.__proto__ = {foo: 'bar'}
kzh

Eu acho que entendi seu ponto.
ComicScrip 26/11/19

120

A propriedade prototype é criada quando uma função é declarada.

Por exemplo:

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

Person.prototypeA propriedade é criada internamente quando você declara a função acima. Muitas propriedades podem ser adicionadas ao Person.prototype que são compartilhadas por instâncias de Person criadas usando new Person ().

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

Vale a pena notar que Person.prototypeé umObject por padrão, literal (pode ser alterado conforme necessário).

Toda instância criada usando new Person()possui uma __proto__propriedade que aponta para o Person.prototype. Essa é a cadeia usada para percorrer para encontrar uma propriedade de um objeto específico.

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

cria 2 instâncias de Person, esses 2 objetos podem chamar o agemétodo de Person.prototypecomo person1.age,person2.age .

Na figura acima da sua pergunta, você pode ver que Fooé um Function Objecte, portanto, ele possui um __proto__link para o Function.prototypequal, por sua vez, é uma instância Objecte possui um __proto__link para Object.prototype. O link proto termina aqui com __proto__o Object.prototypeapontar paranull .

Qualquer objeto pode ter acesso a todas as propriedades em sua cadeia de proto, conforme vinculado por __proto__ de protótipos, , formando a base para a herança prototípica.

__proto__ não é uma maneira padrão de acessar a cadeia de protótipos, a abordagem padrão, mas similar, é usar Object.getPrototypeOf(obj) .

Código abaixo para instanceof operador fornece uma melhor compreensão:

O instanceofoperador de classe de objeto retorna truequando um objeto é uma instância de uma classe, mais especificamente se Class.prototypefor encontrado na cadeia proto desse objeto, o objeto é uma instância dessa classe.

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

O método acima pode ser chamado como: instanceOf.call(object, Class)que retorna true se o objeto for uma instância da Class.


2
Fiquei me perguntando por que o prototypeobjeto foi criado internamente em primeiro lugar? Alguém poderia simplesmente atribuir métodos estáticos ao próprio objeto de função. por exemplo function f(a){this.a = a}; f.increment = function(){return ++this.a}? Por que não foi escolhido esse caminho ao adicionar os métodos ao prototypeobjeto? Isso funcionará se f.__proto__ = gonde g for a classe base.
Abhisekp

Talvez o prototypeobjeto tenha sido escolhido para compartilhamento porque apenas as propriedades exclusivas do construtor da função podem ser armazenadas no objeto do construtor da função.
Abhisekp 01/07/19

1
Na verdade, isso seria uma bagunça, porque instanceofresultaria em ({}) instanceof Function === truecomo não haveria maneira de diferenciar entre protótipos se a prototypepropriedade fosse removida.
Abhisekp 01/07/19

@abhisekp O que você quer dizer com isso: "Isso funcionará se f .__ proto__ = g, em que g é a classe base." Não sei se isso tem algum significado que eu não entendo, mas se você adicionasse as propriedades e métodos dessa maneira, quando usasse a newpalavra-chave para criar uma instância, as propriedades e os métodos não seriam copiados sobre.
DoubleOrt 07/09

67

Uma boa maneira de pensar nisso é ...

prototypeé usado por constructor()funções. Deveria realmente ter sido chamado de algo como,"prototypeToInstall" , já que é isso que é.

e __proto__é esse "protótipo instalado" em um objeto (que foi criado / instalado no objeto a partir da referida constructor()função)


2
Votei positivamente, mas talvez o motivo tenha sido o voto negativo, porque a declaração "protótipo é usado por funções constructor ()" pode parecer que funções não construtoras não possuem, o que não é o caso, mas além disso, agora não é nosso foco agora pode-se notar que cada função é potencialmente um construtor se for chamado com o novo ...
halb yoel

2
Altere " constructor()funções" para "funções construtoras", pois pode haver confusão com " __proto__.constructor()funções". Considero isso importante, pois o construtor __proto __. Na verdade não é chamado quando uma newpalavra-chave é usada.
Alexander Gonchiy 8/08/2015

1
A afirmação de que "o protótipo é usado pelas funções constructor () " conta apenas parte de um fato importante, mas de uma maneira que provavelmente leva os leitores a pensar que é o fato todo. O protótipo é criado internamente para todas as declarações de funções em Javascript, independentemente de como essa função será chamada no futuro - com ou sem a nova palavra-chave; O protótipo de uma função declarada aponta para um literal de objeto.
Yiling

62

Para explicar, vamos criar uma função

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

Quando o JavaScript executa esse código, ele adiciona prototypepropriedade a a, prototypeproperty é um objeto com duas propriedades:

  1. constructor
  2. __proto__

Então, quando fazemos

a.prototype retorna

     constructor: a  // function definition
    __proto__: Object

Agora, como você pode ver, constructornada mais é do que a aprópria função e __proto__aponta para o nível raizObject do JavaScript.

Vamos ver o que acontece quando usamos a afunção com newpalavra-chave.

var b = new a ('JavaScript');

Quando o JavaScript executa esse código, ele faz 4 coisas:

  1. Ele cria um novo objeto, um objeto vazio // {}
  2. Ele cria __proto__em be torna apontam para a.prototypeassimb.__proto__ === a.prototype
  3. Ele é executado a.prototype.constructor(que é a definição da função a) com o objeto recém-criado (criado na etapa 1) como seu contexto (isto), portanto, a namepropriedade transmitida como 'JavaScript' (adicionada athis ) é adicionada ao objeto recém-criado.
  4. Ele retorna o objeto recém-criado em (criado na etapa 1), para que var bseja atribuído ao objeto recém-criado.

Agora, se adicionarmos a.prototype.car = "BMW"e fizermos b.car , a saída "BMW" será exibida.

isso ocorre porque, quando o JavaScript executou esse código, ele procurou por carpropriedades b, ele não encontrou o JavaScript usado b.__proto__(que foi feito para apontar para 'a.prototype' na etapa 2) e encontra a carpropriedade, então retorne "BMW".


2
1. constructornão retorna a()! Retorna a. 2. __proto__retorna Object.prototype, não o objeto raiz em Javascript.
precisa saber é o seguinte

1
Esta é uma ótima resposta!
john-raymon

+1 é a melhor resposta para explicar o que realmente é o protótipo (um objeto com duas propriedades) e como o Javascript executa cada parte do código. Esta informação é surpreendentemente difícil de encontrar.
java-addict301

53

Protótipo VS. __proto__ VS. [[Protótipo]]

Ao criar uma função, um objeto de propriedade chamado prototype está sendo criado automaticamente (você não a criou por si mesmo) e está sendo anexado ao objeto da função (the constructor).
Nota : Este novo protótipo objeto de também aponta para, ou possui um link interno-privado, para o Objeto JavaScript nativo.

Exemplo:

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;
}

Se você criar um novo objeto Foousando a newpalavra - chave, estará basicamente criando (entre outras coisas) um novo objeto que possui um link interno ou privado ao Fooprotótipo da função que discutimos anteriormente:

var b = new Foo();

b.[[Prototype]] === Foo.prototype  // true


A ligação privada ao objeto dessa função chamada protótipo de colchetes duplos ou apenas [[Prototype]]. Muitos navegadores estão nos fornecendo um vínculo público chamado__proto__ !

Para ser mais específico, __proto__é na verdade uma função getter que pertence ao objeto JavaScript nativo. Ele retorna a ligação de protótipo interno-privado de qualquer que seja a thisligação (retorna a [[Prototype]]de b):

b.__proto__ === Foo.prototype // true

Vale ressaltar que, a partir de ECMAScript5, você também pode usar o método getPrototypeOf para obter a ligação privada interna:

Object.getPrototypeOf(b) === b.__proto__ // true


NOTA: esta resposta não pretende cobrir todo o processo de criação de novos objetos ou novos construtores, mas para ajudar a compreender melhor o que é __proto__, prototypee [[Prototype]]e como ele funciona.


2
@ Taurus, clique no cabeçalho, ele leva ao documento de especificações do ECMAScript. Confira a seção 9 (Comportamentos de objetos comuns e exóticos), que explica muito mais detalhes.
Lior Elrom

Acho que há algum erro aqui: _ um novo objeto que possui um link interno ou privado ao protótipo da função Foo_ Você quer dizer: um novo objeto que possui um link interno ou privado ao protótipo da função Foo ?
Koray Tugay

1
Obrigado @KorayTugay! Sim, eu
escrevi

31

Para deixar um pouco claro, além das ótimas respostas acima:

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

var eve = new Person("Eve");

eve.__proto__ == Person.prototype //true

eve.prototype  //undefined

As instâncias têm __proto__ , as classes têm protótipo .


12

Em JavaScript, uma função pode ser usada como construtor. Isso significa que podemos criar objetos a partir deles usando a nova palavra-chave. Toda função de construtor vem com um objeto interno encadeado com eles. Este objeto interno é chamado de protótipo.Instances of a constructor function use __proto__ to access the prototype property of its constructor function.

diagrama de protótipo

  1. Primeiro, criamos um construtor: function Foo(){}. Para ser claro, Foo é apenas outra função. Mas podemos criar um objeto a partir dele com a nova palavra-chave. É por isso que chamamos de função construtora

  2. Toda função possui uma propriedade única, chamada propriedade prototype. Portanto, a função Constructor Foopossui uma propriedade prototype que aponta para seu protótipo, que é Foo.prototype(veja a imagem).

  3. As funções de construtor são elas próprias uma função que é uma instância de um construtor de sistema chamado construtor [[Function]]. Então, podemos dizer que function Fooé construído por um construtor [[Function]]. Então, __proto__do nosso Foo functionapontaremos para o protótipo de seu construtor, que é Function.prototype.

  4. Function.prototypeO próprio é nada mais que um objeto construído a partir de outro construtor de sistema chamado [[Object]]. Então, [[Object]]é o construtor de Function.prototype. Então, podemos dizer que Function.prototypeé uma instância de [[Object]]. Então, __proto__de Function.prototypepontos para Object.prototype.

  5. Object.prototypeé o último homem da cadeia de protótipos. Quero dizer, não foi construído. Já está lá no sistema. Portanto, __proto__aponta para null.

  6. Agora chegamos a instâncias de Foo. Quando criamos uma instância usando new Foo(), ele cria um novo objeto do qual é uma instância Foo. Isso significa que Fooé o construtor dessas instâncias. Aqui criamos duas instâncias (x e y). __proto__de x e y, portanto, aponta para Foo.prototype.


Só para esclarecer: as instâncias não têm propriedade .prototype? Somente o construtor funciona, certo? ... Portanto, a diferença entre uma instância e sua função construtora é: as funções construtoras possuem 1. objeto proto 2. protótipo, enquanto as instâncias possuem apenas propriedade .__ proto__ ... correto?
Shaz

@ Shaz você está certo. As instâncias usam seu proto para acessar a propriedade prototype de sua função construtora.
precisa saber é o seguinte

Mas por que razão é quando você escreve: var car = Object.create (Vehicle); você receberá car .__ proto__ = Veículo MAS também obtém uma propriedade car.prototype que aponta para Vehicle.prototype?
Shaz

@ shaz você pode fornecer um jsfiddle para que eu possa visualizar a situação?
precisa saber é o seguinte

1
aqui car.prototype é uma propriedade herdada. O carro herda a propriedade 'prototype' da função do veículo. então car.prototype === vehicle.prototype. A propriedade "prototype" é uma propriedade no veículo. o carro pode acessá-lo através de sua cadeia de protótipos. Espero que este irá limpar a sua confusão
AL-Zami

8

Resumo:

A __proto__propriedade de um objeto é uma propriedade que mapeia para a prototypefunção construtora do objeto. Em outras palavras:

instance.__proto__ === constructor.prototype // true

Isso é usado para formar a prototypecadeia de um objeto. A prototypecadeia é um mecanismo de pesquisa de propriedades em um objeto. Se a propriedade de um objeto for acessada, o JavaScript procurará primeiro o próprio objeto. Se a propriedade não for encontrada lá, ela subirá atéprotochain até que seja encontrada (ou não)

Exemplo:

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 

Nosso primeiro log resulta true, porque, como mencionado, a __proto__propriedade da instância criada pelo construtor se refere aoprototype propriedade do construtor. Lembre-se, em JavaScript, funções também são objetos. Os objetos podem ter propriedades, e uma propriedade padrão de qualquer função é uma propriedade chamada prototype.

Então, quando essa função é utilizada como uma função construtora, o objeto instanciado a partir dela receberá uma propriedade chamada __proto__. E essa __proto__propriedade se refere à prototypepropriedade da função construtora (que por padrão todas as funções possuem).

Por que isso é útil?

O JavaScript possui um mecanismo ao procurar propriedades nas Objectsquais é chamada 'herança prototípica' , eis o que basicamente faz:

  • Primeiro, é verificado se a propriedade está localizada no próprio objeto. Nesse caso, essa propriedade é retornada.
  • Se a propriedade não estiver localizada no próprio objeto, ela 'subirá o protochain'. Basicamente, analisa o objeto referido pela __proto__propriedade. Lá, ele verifica se a propriedade está disponível no objeto referido por __proto__.
  • Se a propriedade não estiver localizada no __proto__objeto, ela subirá a __proto__cadeia, até o Objectobjeto.
  • Se não conseguir encontrar a propriedade em nenhum lugar do objeto e sua prototypecadeia, ele retornará undefined.

Por exemplo:

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

let mySelf = new Person('Willem');

console.log(mySelf.__proto__ === Person.prototype);

console.log(mySelf.__proto__.__proto__ === Object.prototype);


7

Por acaso, estou aprendendo o protótipo de You Don't Know JS: this & Object Prototypes , que é um livro maravilhoso para entender o design abaixo e esclarecer muitos equívocos (é por isso que estou tentando evitar o uso de herança e coisas assim instanceof).

Mas eu tenho a mesma pergunta que as pessoas fizeram aqui. Várias respostas são realmente úteis e esclarecedoras. Eu também adoraria compartilhar meus entendimentos.


O que é um protótipo?

Objetos em JavaScript têm uma propriedade interna, indicada na especificação como [[Prototype]], que é simplesmente uma referência a outro objeto. Quase todos os objetos recebem um não-null valor para essa propriedade, no momento de sua criação.

Como obter o protótipo de um objeto?

via __proto__ouObject.getPrototypeOf

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

Qual é o prototype?

prototypeé um objeto criado automaticamente como uma propriedade especial de uma função , usada para estabelecer a cadeia de delegação (herança), também conhecida como cadeia de protótipo.

Quando criamos uma função a, prototypeé automaticamente criado como uma propriedade especial sobre ae salva o código de função em que o constructoron prototype.

function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true

Eu adoraria considerar essa propriedade como o local para armazenar as propriedades (incluindo métodos) de um objeto de função. Essa também é a razão pela qual funções utilitárias em JS são definidas como Array.prototype.forEach(),Function.prototype.bind() ,Object.prototype.toString().

Por que enfatizar a propriedade de uma função ?

{}.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();

Assim, Arary, Function, Objectestão todas as funções. Devo admitir que isso atualiza minha impressão em JS. Eu sei que funções são cidadãos de primeira classe em JS, mas parece que ele é construído sobre funções.

Qual é a diferença entre __proto__e prototype?

__proto__uma referência funciona em cada objeto para se referir à sua [[Prototype]]propriedade.

prototypeé um objeto criado automaticamente como uma propriedade especial de uma função , usada para armazenar as propriedades (incluindo métodos) de um objeto de função.

Com esses dois, podemos mapear mentalmente a cadeia de protótipos. Como esta figura ilustra:

function Foo() {}
var b = new Foo();

b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true

7

 Protótipo JavaScript vs __prototype__

'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

Em JavaScript, todo objeto (a função também é objeto!) Tem uma __proto__propriedade, a propriedade é referência ao seu protótipo.

Quando usamos o newoperador com um construtor para criar um novo objeto, a __proto__propriedade do novo objeto será definida com a prototypepropriedade do construtor; o construtor será chamado pelo novo objeto, nesse processo "this" será uma referência ao novo objeto no escopo do construtor, finalmente retorne o novo objeto.

O protótipo do construtor é __proto__propriedade, a prototypepropriedade do construtor é o trabalho com o newoperador.

O construtor deve ser uma função, mas a função nem sempre é construtora, mesmo que tenha prototypepropriedade.

A cadeia de protótipos na verdade é __proto__propriedade do objeto para fazer referência ao seu protótipo, e a __proto__propriedade do protótipo para fazer referência ao protótipo do protótipo e assim por diante, até fazer referência à __proto__propriedade do protótipo do objeto que é referência a nulo.

Por exemplo:

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

[[Prototype]]e __proto__propriedade é realmente a mesma coisa.

Podemos usar o método getPrototypeOf do Object para obter o protótipo de algo.

console.log(Object.getPrototypeOf(a) === a.__proto__); // true

Qualquer função que escrevemos pode ser usada para criar um objeto com o newoperador, para que qualquer uma dessas funções possa ser um construtor.


6

Outra boa maneira de entender isso:

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);

Somente após o IE11 __proto__ser suportado. Antes dessa versão, como o IE9, você poderia usar o constructorpara obter o __proto__.


Só que eu iria escrever o contrário: foo .__ proto__ === foo.constructor.prototype
epeleg

6

protótipo

prototype é uma propriedade de uma Function. É o modelo para criar objetos usando essa função (construtora) com a nova palavra-chave.

__proto__é usado na cadeia de pesquisa para resolver métodos, propriedades. quando um objeto é criado (usando a função construtora com a nova palavra-chave), __proto__é definido como (Construtor) Function.prototype

function Robot(name) {
    this.name = name;
}
var robot = new Robot();

// the following are true   
robot.__proto__ == Robot.prototype
robot.__proto__.__proto__ == Object.prototype

Aqui está minha explicação (imaginária) para esclarecer a confusão:

Imagine que exista uma classe imaginária (blueprint / coockie cutter) associada à função. Essa classe imaginária é usada para instanciar objetos. prototypeé o mecanismo de extensão (método de extensão em C # ou extensão rápida) para adicionar itens a essa classe imaginária.

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

O acima pode ser imaginado como:

// 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;
    }

} 

Assim,

var robot = new Robot();

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

Agora adicionando método ao prototypedo Robot:

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)

O acima pode ser imaginado como extensão da classe Robot:

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

Que por sua vez,

// 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
    };
}

ainda pensando em nomes mais coerentes para __proto__e protótipo. talvez protótipo e herança?
Dmitry

Eu diria, prototypee __proto__ambos devem ser evitados. Temos aula agora e eu gosto de OOP.
Hassan Tareq

o problema é que a classe é relativamente nova e não é suportada por mecanismos realmente convenientes, como o Microsoft JScript (é bom ter ao trabalhar em C e precisa de um mecanismo de script rápido e sujo que esteja sempre lá) e o nashorn javascript (que vem com todos os novas instalações Java sob jjs e é uma boa maneira de colocar o Java em um ambiente dinâmico puro, onde você não precisa recompilar constantemente as coisas). O problema é que se a classe fosse açúcar, não seria um problema, mas não é, oferece coisas que são impossíveis sem elas nas versões js mais antigas. Como estender "Função".
Dmitry

Eventualmente, obteremos suporte. Sou desenvolvedor back-end, então não tenho problemas, codifico js raramente.
Hassan Tareq

e herdar membros estáticos de uma maneira que a adição / remoção de membros estáticos do pai seja percebida pelo filho (o que não consigo pensar em uma maneira de fazer no JScript, que não oferece Object.assign / __ proto __ / getPrototypeOf, então você tem que mexer com o Object.prototype raiz para simulá-lo)
Dmitry

4

Simplificando:

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

Isso permite anexar propriedades ao X.prototype após a instanciação de objetos do tipo X, e eles ainda terão acesso a essas novas propriedades através da referência __proto__ que o mecanismo Javascript usa para percorrer a cadeia de protótipos.


4

Prototype ou Object.prototype é uma propriedade de um objeto literal. Ele representa o objeto de protótipo de objeto que você pode substituir para adicionar mais propriedades ou métodos ao longo da cadeia de protótipos.

__proto__ é uma propriedade do acessador (função get e set) que expõe o protótipo interno de um objeto através do qual ele é acessado.

Referências:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
  2. http://www.w3schools.com/js/js_object_prototypes.asp

  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto


Object.prototypenão é uma propriedade de um objeto literal, tentando imprimir {}.prototyperetornos indefinidos; no entanto, pode ser acessado via {}.__proto__, que retorna Object.prototype.
DoubleOrt 7/09

3

Eu sei, estou atrasado, mas deixe-me tentar simplificá-lo.

Digamos que existe uma função

    function Foo(message){

         this.message = message ; 
     };

     console.log(Foo.prototype);

A função Foo terá um objeto protótipo vinculado. Portanto, sempre que criamos uma função em JavaScript, ela sempre tem um objeto de protótipo vinculado a ela.

Agora vamos em frente e crie dois objetos usando a função Foo.

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);
  1. Agora temos dois objetos, objeto ae objeto b. Ambos são criados usando o construtor Foo. Lembre-se de que construtor é apenas uma palavra aqui.
  2. Os objetos aeb têm uma cópia da propriedade da mensagem.
  3. Esses dois objetos aeb estão vinculados ao objeto de protótipo do construtor Foo.
  4. Nos objetos aeb, podemos acessar o protótipo Foo usando a propriedade proto em todos os navegadores e no IE podemos usar Object.getPrototypeOf (a) ou Object.getPrototypeOf (b)

Agora, Foo.prototype, a. proto e b. proto tudo indica o mesmo objeto.

    b.__proto__ === Object.getPrototypeOf(a);
    a.__proto__ ===  Foo.prototype;
    a.constructor.prototype  === a.__proto__;

tudo acima retornaria verdadeiro.

Como sabemos, no JavaScript, as propriedades podem ser adicionadas dinamicamente. Podemos adicionar propriedade ao objeto

    Foo.prototype.Greet = function(){

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

Como você vê, adicionamos o método Greet () no Foo.prototype, mas ele pode ser acessado em aeb ou em qualquer outro objeto construído usando Foo.

Ao executar a.Greet (), o JavaScript primeiro pesquisará Greet no objeto a na lista de propriedades. Ao não encontrar, ele subirá na cadeia proto de a. Desde um. proto e Foo.prototype é o mesmo objeto, o JavaScript encontrará o método Greet () e o executará.

Espero que agora protótipo e proto sejam um pouco simplificados.


3

Exemplo explicativo:

function Dog(){}
Dog.prototype.bark = "woof"

let myPuppie = new Dog()

agora, myPupppie possui uma __proto__propriedade que aponta para Dog.prototype.

> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}

mas myPuppie NÃO possui uma propriedade prototype.

> myPuppie.prototype
>> undefined

Portanto, __proto__de mypuppie é a referência à propriedade .prototype da função construtora que foi usada para instanciar esse objeto (e o atual objeto myPuppie possui um "delegado para" o relacionamento com este__proto__ ), enquanto a propriedade .prototype de myPuppie está simplesmente ausente (desde nós não o definimos).

Boa explicação por MPJ ​​aqui: proto vs prototype - Criação de Objetos em JavaScript


3

Fiz para mim um pequeno desenho que representa o seguinte trecho de código:

var Cat = function() {}
var tom = new Cat()

Entendendo __proto__ e protótipo

Eu tenho um histórico clássico de OO, portanto, foi útil representar a hierarquia dessa maneira. Para ajudá-lo a ler este diagrama, trate os retângulos na imagem como objetos JavaScript. E sim, funções também são objetos. ;)

Objetos em JavaScript têm propriedades e __proto__é apenas um deles.

A idéia por trás dessa propriedade é apontar para o objeto ancestral na hierarquia (herança).

O objeto raiz no JavaScript é Object.prototypee todos os outros objetos são descendentes deste. A __proto__propriedade do objeto raiz é null, que representa o fim da cadeia de herança.

Você notará que isso prototypeé uma propriedade das funções. Caté uma função, mas também Functione Objectsão funções (nativas). tomnão é uma função, portanto, não possui essa propriedade.

A idéia por trás dessa propriedade é apontar para um objeto que será usado na construção, ou seja, quando você chama o newoperador nessa função.

Observe que os objetos protótipos (retângulos amarelos) têm outra propriedade chamada constructorque aponta de volta para o respectivo objeto de função. Por razões de brevidade, isso não foi descrito.

De fato, quando criamos o tomobjeto com new Cat(), o objeto criado terá a __proto__propriedade definida como o prototypeobjeto da função construtora.

No final, vamos brincar um pouco com esse diagrama. As seguintes afirmações são verdadeiras:

  • tom.__proto__A propriedade aponta para o mesmo objeto que Cat.prototype.

  • Cat.__proto__aponta para o Function.prototypeobjeto, como Function.__proto__e Object.__proto__faz.

  • Cat.prototype.__proto__e tom.__proto__.__proto__aponte para o mesmo objeto e é isso Object.prototype.

Felicidades!


Muito bem explicado!
StackOverflow UI

@ theshinylight, tom.__proto__e Cat.prototypesão estritamente iguais, Então, tom.__proto__ === Cat.prototype e Cat.prototype === tom.__proto__são verdadeiras. Então, o que você quis dizer com seta na imagem?
aXuser264 20/01

A seta preta (se você estiver se referindo a ela) não tem um significado específico, além da propriedade do objeto. O mesmo prototypeacontece com a propriedade do Catobjeto (da sua pergunta).
theshinylight

2

DEFINIÇÕES

(número entre parênteses () é um 'link' para o código que está escrito abaixo)

prototype- um objeto que consiste em:
=> funções (3) deste particular ConstructorFunction.prototype(5) acessíveis por cada objeto (4) criado ou a ser criado através dessa função construtora (1)
=> a própria função construtora (1) )
=> __proto__deste objeto em particular (objeto de protótipo)

__proto__ (dandor proto?) - um link ENTRE qualquer objeto (2) criado por meio de uma função específica do construtor (1) E as propriedades do objeto de protótipo (5) desse construtor que permitem que cada objeto criado (2) tenha acesso às funções do protótipo e métodos (4) (__proto__ por padrão, está incluído em todos os objetos em JS)

ESCLARECIMENTO DE CÓDIGO

1

    function Person (name, age) {
        this.name = name;
        this.age = age;} 

2)

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

3)

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

4)

    John.getOlder();

5)

    Person.prototype;

1

Vou tentar uma explicação da quarta série:

As coisas são muito simples. A prototypeé um exemplo de como algo deve ser construído. Assim:

  • Sou um functione construo novos objetos semelhantes aos meusprototype

  • Eu sou um objecte fui construído usando o meu __proto__como exemplo

prova :

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

1
Não, nem prototypenem a __proto__são usados ​​a qualquer momento como um blueprint para criar qualquer objeto. Este é um mito introduzido pela classsintaxe embaçada e seus antecessores. Como o post de resposta diz, ele é usado apenas para a cadeia de pesquisa e, no caso de prototypese identificar, é constructorusado new(o que faz parte do mecanismo de fingir ser elegante que confunde muitos usuários, inclusive eu).
Christof Kälin

O primeiro ponto deve ser "Sou uma função e construo novos objetos que serão delegados ao meu protótipo"
Nitin Jadhav

1

Toda função que você cria tem uma propriedade chamada prototypee ela inicia sua vida como um objeto vazio. Esta propriedade é inútil até que você use essa função como função construtora, ou seja, com a palavra-chave 'new'.

Isso geralmente é confundido com a __proto__propriedade de um objeto. Alguns podem ficar confusos e, exceto que a prototypepropriedade de um objeto pode obter o proto de um objeto. Mas este não é o caso. prototypeé usado para obter o __proto__objeto criado a partir de um construtor de função.

No exemplo acima:

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__

Eu espero que faça sentido.


1
prototypenão é usado para criar o __proto__objeto. __proto__, quando acessado, apenas fornece uma referência ao prototypeobjeto.
doubleOrt

1

Que tal usar __proto__para métodos estáticos?

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

É exatamente por isso que uma resposta a " __proto__VS. prototypeem JavaScript" ?
Andreas

é bom ou o que sobre Foo.collection.push (this) Foo.count ++
Selva Ganapathi

1

(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) 
    })()

Experimente este código para entender


1

Há apenas um objeto usado para encadeamento protípico. Obviamente, esse objeto tem um nome e um valor: __proto__é seu nome e prototypeé seu valor. Isso é tudo.

para facilitar ainda mais a compreensão, veja o diagrama na parte superior deste post (diagrama de dmitry soshnikov), você nunca encontrará __proto__pontos para outra coisa senãoprototype seu valor.

A essência é a seguinte: __proto__é o nome que faz referência ao objeto prototípico e prototypeé o objeto prototípico real.

É como dizer:

let x = {name: 'john'};

xé o nome do objeto (ponteiro) e {name: 'john'}é o objeto real (valor dos dados).

NOTA: esta é apenas uma dica massivamente simplificada de como eles estão relacionados em um nível alto.

Atualização: Aqui está um exemplo simples de javascript concreto para melhor ilustração:

let x = new String("testing") // Or any other javascript object you want to create

Object.getPrototypeOf(x) === x.__proto__; // true

Isso significa que, quando Object.getPrototypeOf(x)o valor real de x(qual é o seu protótipo), é exatamente o que o __proto__de xestá apontando. Portanto, __proto__está de fato apontando para o protótipo de x. Assim, faz __proto__referência x(ponteiro de x) e prototypeé o valor de x(seu protótipo).

Espero que esteja um pouco claro agora.


1

Essa é uma pergunta muito importante e relevante para quem deseja entender a herança prototípica. Pelo que entendi, o protótipo é atribuído por padrão quando um objeto é criado com o novo de uma função porque Function possui um objeto de protótipo por definição:

function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]

Quando criamos um objeto comum sem novo, ou seja, explicitamente a partir de uma função, ele não possui protótipo, mas possui um proto vazio ao qual pode ser atribuído um protótipo.

var foo={
  check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); //  TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo

Podemos usar Object.create para vincular um objeto explicitamente.

// we can create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.fooprops= "We checking prototypes";
console.log(bar.__proto__); // "foo"
console.log(bar.fooprops); // "We checking prototypes"
console.log(bar.check); // 10 is delegated to `foo`

0

__proto__é a base para construir prototypee uma função construtora, por exemplo: function human(){}has, prototypeque é compartilhada via __proto__na nova instância da função construtora. Uma leitura mais detalhada aqui


@ Daniel Daniel: não sei por que você votou negativamente, mas a edição que você fez não foi o que eu estava tentando transmitir. Editado ainda mais para mais folga :).
Jyoti Duhan

Jyoti, eu não para baixo votar a sua resposta, alguém fez, eu apenas editado :)
Freelancer

0

Como isso afirmou corretamente

__proto__é o objeto real usado na cadeia de pesquisa para resolver métodos, etc. prototype é o objeto usado para criar __proto__quando você cria um objeto com new:

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

Podemos observar ainda que a __proto__propriedade de um objeto criado usando o construtor de funções aponta para o local da memória apontado pelo protótipo propriedade desse respectivo construtor.

Se alterarmos o local da memória do protótipo da função construtora, o __proto__objeto derivado continuará apontando para o espaço de endereço original. Portanto, para disponibilizar propriedades comuns na cadeia de herança, sempre acrescente propriedades ao protótipo de função do construtor , em vez de reinicializá-lo (o que alteraria seu endereço de memória).

Considere o seguinte exemplo:

function Human(){
    this.speed = 25;
}

var himansh = new Human();

Human.prototype.showSpeed = function(){
    return this.speed;
}

himansh.__proto__ === Human.prototype;  //true
himansh.showSpeed();    //25

//now re-initialzing the Human.prototype aka changing its memory location
Human.prototype = {lhs: 2, rhs:3}

//himansh.__proto__ will still continue to point towards the same original memory location. 

himansh.__proto__ === Human.prototype;  //false
himansh.showSpeed();    //25

-1

meu entendimento é: __proto__ e prototype são todos servidos para a técnica de cadeia de protótipos. a diferença é que funções nomeadas com sublinhado (como __proto__) não são direcionadas a desenvolvedores chamados explicitamente. em outras palavras, eles são apenas para alguns mecanismos, como herdar etc. são 'back-end'. mas funções nomeadas sem sublinhado são projetadas para serem chamadas explicitamente, elas são 'front-end'.


3
Há mais de __proto__e prototype, do que apenas a convenção de nomenclatura. Eles podem ou não apontar para o mesmo objeto. Consulte a resposta @zyklus.
Demisx

1
@ Demisx é claro que você disse que está certo, mas minha opinião é diferença de nome exposto o contraste da funcionalidade.
Beicai 11/10

Não é apenas o suficiente para o estado "como por sua compreensão", especialmente quando outras respostas boas foram fornecidos antes ...
ProfNandaa

-3

!!! ESTA É A MELHOR EXPLICAÇÃO DO MUNDO !!!!!

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

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

no mecanismo javascript dos construtores de funções chama isso q.__proto__ = prototypeautomaticamente quando escrevemos new Classe no __proto__conjunto de propsClass.prototype

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

Desfrutar %)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.