__proto__ VS. прототип в JavaScript - PullRequest
       91

__proto__ VS. прототип в JavaScript

707 голосов
/ 01 апреля 2012

Этот рисунок снова показывает, что у каждого объекта есть прототип. Конструктор Функция Foo также имеет свой собственный __proto__, который является Function.prototype, и который в свою очередь также ссылается через свойство __proto__ снова на Object.prototype. Таким образом, повторяю, Foo.prototype просто явный свойство Foo, которое относится к прототипу объектов b и c.

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

В чем различия между __proto__ и prototype свойствами?

enter image description here

Цифра взята из здесь .

Ответы [ 25 ]

5 голосов
/ 14 сентября 2017

прототип

прототип является свойством функции. Это план создания объектов с помощью этой функции (конструктора) с ключевым словом new.

__ прото __

__proto__ используется в цепочке поиска для разрешения методов, свойств. когда объект создается (используя функцию конструктора с новым ключевым словом), __proto__ устанавливается в (Конструктор) 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

Вот мое (воображаемое) объяснение, чтобы устранить путаницу:

Представьте себе, что существует некий воображаемый класс (планер / резак), связанный с функцией. Этот воображаемый класс используется для создания объектов. prototype - это механизм расширения (метод расширения в C # или Swift Extension) для добавления объектов в этот воображаемый класс.

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

Выше можно представить как:

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

Вышесказанное можно представить как расширение класса Robot:

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

Что, в свою очередь,

// 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
    };
}
4 голосов
/ 05 августа 2018

JavaScript prototype 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

В JavaScript каждый объект (функция также является объектом!) Имеет свойство __proto__, свойство является ссылкой на его прототип.

Когда мы используем оператор new с конструктором для создания нового объекта, свойство __proto__ нового объекта будет установлено со свойством prototype конструктора, тогда конструктор будет вызываться новым объектом, вэтот процесс «this» будет ссылкой на новый объект в области конструктора, и, наконец, вернет новый объект.

Прототип конструктора - это свойство __proto__, свойство prototype конструктора работает с newoperator.

Конструктор должен быть функцией, но функция не всегда является конструктором, даже если она имеет свойство prototype.

Цепочка прототипа фактически является свойством __proto__ объекта для ссылки на его прототип, исвойство __proto__ прототипа для ссылки на прототип прототипа и т. д., до ссылки на свойство __proto__ прототипа объекта, которое ссылается на ноль.

Например: свойства

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]] и __proto__ на самом деле одно и то же.

Мы можем использовать метод getPrototypeOf объекта для получения прототипа чего-либо.

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

Любую написанную нами функцию можно использовать для создания объекта с оператором new, поэтому любая из этих функций может быть конструктором.

4 голосов
/ 24 октября 2015

Проще говоря:

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

Это позволяет вам присоединять свойства к X.prototype. Объекты AFTER типа X были созданы, и они все равно получат доступ к этим новым свойствам через ссылку __proto__, которую движок Javascript использует для прохождения по цепочке прототипов.

3 голосов
/ 23 сентября 2016

Я знаю, я опоздал, но позвольте мне попытаться упростить это.

Допустим, есть функция

    function Foo(message){

         this.message = message ; 
     };

     console.log(Foo.prototype);

Функция Foo будет связана с объектом-прототипом.Поэтому всякий раз, когда мы создаем функцию в JavaScript, с ней всегда связан объект-прототип.

Теперь давайте продолжим и создадим два объекта, используя функцию Foo.

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);
  1. Теперь у нас есть два объекта: объект a и объект b.Оба созданы с помощью конструктора Foo.Имейте в виду, конструктор это просто слово здесь.
  2. Объект a и b оба имеют копию свойства сообщения.
  3. Эти два объекта a и b связаны с прототипом объекта конструктора Foo.
  4. На объектах a и b, мы можем получить доступ к прототипу Foo, используя свойство proto во всех браузерах, а в IE мы можем использовать Object.getPrototypeOf (a) или Object.getPrototypeOf (b)

Now, Foo.прототип, a. proto и b. proto все обозначают один и тот же объект.

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

все вышеперечисленное вернет true.

Как известно, в JavaScript свойства могут добавляться динамически.Мы можем добавить свойство к объекту

    Foo.prototype.Greet = function(){

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

Как вы видите, мы добавили метод Greet () в Foo.prototype, но он доступен в a и b или любом другом объекте, который построен с использованием Foo.

При выполнении a.Greet () JavaScript сначала будет искать Greet в объекте a в списке свойств.Если он не найден, он поднимется в цепочку proto .Поскольку a. proto и Foo.prototype - это один и тот же объект, JavaScript найдет метод Greet () и выполнит его.

Надеюсь, теперь прототип и proto немного упрощены.

3 голосов
/ 17 августа 2018

Сводка:

Свойство __proto__ объекта - это свойство, которое сопоставляется с prototype функции конструктора объекта.Другими словами:

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

Используется для формирования цепочки prototype объекта.Цепочка prototype - это механизм поиска свойств объекта.При обращении к свойству объекта JavaScript сначала будет смотреть на сам объект.Если свойство там не найдено, оно поднимется до protochain, пока не будет найдено (или нет)

Пример:

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 объектаконструктор.Помните, что в JavaScript функции также являются объектами.У объектов могут быть свойства, и свойство по умолчанию любой функции - это одно свойство с именем prototype.

Тогда, когда эта функция используется в качестве функции конструктора, объект, экземпляр которого создается, получит свойство с именем __proto__.И это свойство __proto__ ссылается на свойство prototype функции-конструктора (которое по умолчанию есть в каждой функции).

Почему это полезно?

В JavaScript есть механизм при поискесвойства для Objects, который называется 'наследование прототипа' , вот что он в основном делает:

  • Сначала проверяется, находится ли свойство на самом объекте.Если это так, это свойство возвращается.
  • Если свойство не находится на самом объекте, оно будет «подниматься по проточине».Он в основном смотрит на объект, на который ссылается свойство __proto__.Там он проверяет, доступно ли свойство для объекта, на который ссылается __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);
3 голосов
/ 19 ноября 2015

Prototype или Object.prototype - это свойство литерала объекта.Он представляет объект-прототип Object , который можно переопределить, чтобы добавить дополнительные свойства или методы дальше по всей цепочке прототипов.

__ proto __ - это свойство метода доступа (функция get и set), предоставляющее внутренний прототип объекта, к которому он доступен.

Ссылки:

  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

2 голосов
/ 15 июня 2017

Определения

(число в круглых скобках () является «ссылкой» на код, который написан ниже)

prototype - объект, состоящий из:
=> функции (3) этого конкретные ConstructorFunction.prototype (5), которые доступны каждому объект (4), созданный или предназначенный для создания с помощью этой функции конструктора (1)
=> сама функция конструктора (1)
=> __proto__ этого конкретного объекта (прототипа объекта)

__proto__ (dandor proto?) - ссылка между любым объектом (2), созданным с помощью определенной функции-конструктора (1), И свойствами объекта-прототипа (5) этого конструктора, которые позволяют каждому созданный объект (2) для доступа к функциям и методам прототипа (4) (__proto__ по умолчанию включен в каждый отдельный объект в JS)

Уточнение кода

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 голос
/ 16 декабря 2018

Пояснительный пример:

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

let myPuppie = new Dog()

Теперь myPupppie имеет свойство __proto__, которое указывает на Dog.prototype.

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

но myPuppie НЕ имеет свойства прототипа.

> myPuppie.prototype
>> undefined

Итак, __proto__ mypuppie - это ссылка на свойство .prototype функции конструктора, которая использовалась для создания экземпляра этого объекта (а текущий объект myPuppie имеет отношение «делегаты» к этому __proto__ object), в то время как свойство .prototype myPuppie просто отсутствует (поскольку мы его не устанавливали).

Хорошее объяснение MPJ здесь: proto vs prototype - Создание объекта в JavaScript

1 голос
/ 12 января 2017

Я попробую объяснение 4-го класса:

Все очень просто.prototype является примером того, как что-то должно быть построено.Итак:

  • Я 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
1 голос
/ 18 июля 2018

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

Попробуйте этот код, чтобы понять

...