Глубокое понимание прототипа и цепочки прототипов в JavaScript

JavaScript

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность

Эта статья участвовала в "Проект «Звезда раскопок»”, чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.

предисловие

Знание прототипа и цепочки прототипов всегда было в центре внимания при проведении интервью. Давайте начнем с вопроса интервью для аппетита:

function User() {}
User.prototype.sayHello = function() {}
var u1 = new User();
var u2 = new User();
console.log(u1.sayHello === u2.sayHello); 
console.log(User.prototype.constructor); 
console.log(User.prototype === Function.prototype); 
console.log(User.__proto__ === Function.prototype); 
console.log(User.__proto__ === Function.__proto__); 
console.log(u1.__proto__ === u2.__proto__); 
console.log(u1.__proto__ === User.__proto__); 
console.log(Function.__proto__ === Object.__proto__); 
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); 
console.log(Function.prototype.__proto__ === Object.prototype); 

фундамент

  1. JavaScriptВсе объекты по существу проходят черезnew 函数созданных, включая литералы объектов в виде определенных объектов (эквивалентныхnew Object()грамматический сахар).

    对象定义.jfif

  2. new FunctionObject,ArrayЖдать函数定义.jfif

prototype

Каждая функция имеет свойствоprototype, это прототип, по умолчанию обычныйObjectОбъект, являющийся прототипом экземпляра, созданного путем вызова этого конструктора.函数原型.jfif

contructor属性

JavaScriptТакже есть свойства, указывающие на конструктор из прототипа:constructor,Прямо сейчасFunc.prototype.constructor --> Func constructor.jfif

__proto__

JavaScriptВсе объекты в (кромеnull) есть__proto__свойство, указывающее на прототип объекта.

function User() {}
var u1 = new User();
// u1.__proto__ -> User.prototype
console.log(u1.__proto__ === User.prototype) // true

Очевидно, экземпляр__proto__Свойство указывает на прототип конструктора, затем на несколько экземпляров__proto__Укажет ли он на один и тот же прототип?

var u2 = new User();
console.log(u1.__proto__ === u2.__proto__) // true

Если несколько экземпляров__proto__Оба указывают на прототип конструктора, если экземпляр можно запрограммировать в прототипе, если метод, атрибут и т. Д. Можно запрограммировать, и наследование может быть запрограммировано, а эффект наследования может быть запрограммирован.

Продолжим обновлять диаграмму отношений между прототипом и цепочкой прототипов:隐式原型.jfif

Сеть прототипов

Когда объект экземпляра ищет атрибут, если он не может его найти, он будет следовать__proto__Перейдите к прототипу, связанному с объектом, чтобы найти его, если вы не можете его найти, перейдите к прототипу прототипа, пока не найдете верхний уровень, который является концепцией цепочки прототипов.

Вот несколько примеров цепочек прототипов с помощью вопросов интервью:

Пример

  1. u1.sayHello():u1НетsayHellou1.__proto__(User.prototype), успешно получен доступ кsayHelloметод
  2. u2.toString() u2,User.prototypeничегоtoStringметод,User.prototypeUser.prototype.__proto__(Object.prototype)toStringметод

улучшать

function A() {}
function B(a) {
    this.a = a;
}
function C(a) {
    if (a) {
        this.a = a;
    }
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;

console.log(new A().a); //1
console.log(new B().a); //undefined
console.log(new C(2).a); //2

Но чего-то еще не хватает при решении первоначальных вопросов интервью в статье, таких какFunction.__proto__ === Object.__proto__、Function.prototype.__proto__ === Object.prototype.__proto__Подождите, давайте решать это один за другим.

Objcet.__proto__,Object.prototype,Object.prototype.__proto__

  • ObjectЭто конструктор, во второй части мы рассказали все функции черезnew Functionсоздан, так чтоObjectэквивалентноFunctionэкземпляр, то естьObject.__proto__ --> Function.prototype.

  • Object.prototypeдаObjectObject.prototype.__proto__Нет верхнего прототипа, на который можно было бы указать, поэтому его значение равноnull

// 总结:
Object.__proto__ --> Function.prototype
Object.prototype.__proto__ --> null

Function.__proto__,Function.prototype,Function.prototype.__proto__

  • Function.prototypeдаFunctionПрототип — это прототип всех экземпляров функций, таких как приведенный выше.Object.__proto__
  • Function.prototypeобычный объект, поэтомуFunction.prototype.__proto__ --> Object.prototype
  • Function.__proto__: __proto__указывает на прототип создавшего его конструктора, который его создалFunctionЭто?
    • Гипотеза: объекты-функции также являются объектами, тогдаFunction.__proto__укажет наObject.prototype? упомянутый выше,Object.__proto__ --> Function.prototype. еслиFunction.__proto__ -> Object.prototype, всегда странно, кто кого создал, поэтому я провел тест:

      Function与Object.png

    Практика показала, что толькоObject.__proto__ --> Function.prototype
    • Не результат напряженного мышления, не так ли?FunctionФункция не обезьяна и из щели в камне выпрыгнула? Так что я провел кучу тестов вместе, и я не ожидал найти зацепку.

      Function proto.png

    Из вышеизложенного мы можем получить:Function.__proto__ --> Function.prototype

    FunctionФункция ничего не создает,JSКогда двигатель запустится, добавьте его в память.

Суммировать

Наконец, знание прототипа и цепочки прототипов сводится к картинке:原型链.jfif

  1. Все функции (включаяFunction)из__proto__направлениеFunction.prototype
  2. Экземпляр пользовательского объекта__proto__
  3. функциональныйprototypeиз__proto__направлениеObject.prototype
  4. Object.prototype.__proto__ --> null

послесловие

var F = function () {}
Object.prototype.a = function () {}
Function.prototype.b = function () {}

var f = new F();

console.log(f.a, f.b, F.a, F.b);

// 原型链
// f.__proto__ --> F.prototype --> Object.prototype
// F.__proto__ --> Function.prototype --> Object.prototype

Часть источника этой статьи: Учебные материалы Duyi Education.