Тупо неотличимы __proto__ и прототип

внешний интерфейс JavaScript
Тупо неотличимы __proto__ и прототип

Сегодня мой коллега Xiaoying Children's Shoes задал мне вопрос:

function Foo(firstName, lastName){
    this.firstName = firstName;
    this.lastName = lastName; 
}
Foo.prototype.logName = function(){
    Foo.combineName();
    console.log(this.fullName);
}
Foo.prototype.combineName = function(){
    this.fullName = `${this.firstName} ${this.lastName}`
}

var foo = new Foo('Sanfeng', 'Zhang');
foo.logName(); // Uncaught TypeError: Foo.combineName is not a function

Детская обувь Xiaoying думаетFooОбъект-прототипFoo.prototype,такFooунаследуетFoo.prototypeсвойства, звонитеFoo.combineName()эквивалентно вызовуFoo.prototype.combineName(), но результатFoo.combineName()Не метод.

Причина этой проблемы должна заключаться в том, что детская обувь Xiaoying путает некоторые принципы прототипа и наследования.Давайте разберем связанные принципы прототипа и наследования, чтобы выяснить основную причину проблемы.

prototype

prototypeявляется владельцем[[Construct]]Свойства, доступные только для объектов внутренних методов.

Например, функции, методы объектов,ES6класс в . УведомлениеES6Стрелочные функции нет[[Construct]]метод, так что нетprototypeэто свойство, если вы не добавите его для него.

При создании функцииJavaScriptбудет автоматически добавлено для этой функцииprototypeсвойство, это свойство указывает на объект-прототипFunctionname.prototype. Мы можем добавить свойства или объекты к этому объекту-прототипу или даже указать на существующий объект.

__proto__

Далее мы говорим о наследовании, каждый объект имеет__proto__Атрибут, этот атрибут используется для идентификации прототипа, который он наследует.

Уведомление:JavaScriptЛюбой объект имеет встроенное свойство[[Prototype]], до ES5 не было стандартного способа доступа к этому встроенному свойству, но большинство браузеров поддерживают его через__proto__посетить. Используйте следующие равномерно__proto__посетить[[Prototype]], к которым нельзя получить доступ таким образом в фактической разработке.

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

JavaScriptв состоянии пройтиprototypeа также__proto__Создает связь между двумя объектами, чтобы один объект мог получить доступ к свойствам и функциям другого объекта посредством делегирования.

Одной из таких ассоциаций является цепочка прототипов, конечная цепочка объектов, реализующих наследование и общие свойства.

Конструктор создает экземпляр объекта

JavaScriptФункция имеет два разных внутренних метода:[[Call]]а также[[Construct]].

если не прошелnewключевое слово для вызова функции, а затем выполнить[[Call]]функция, которая непосредственно выполняет тело функции в коде.

когда прошелnewКогда ключевое слово вызывает функцию, выполнение[[Construct]]функция, которая отвечает за создание экземпляра объекта, размещение объекта экземпляра__proto__свойство указывает на конструкторprototypeреализовать унаследованный конструкторprototypeВсе свойства и методы , будутthisПривяжите к экземпляру, а затем выполните тело функции.

Макет конструктора:

function createObject(proto) {
    if (!(proto === null || typeof proto === "object" || typeof proto === "function"){
        throw TypeError('Argument must be an object, or null');
    }
    var obj = new Object();
    obj.__proto__ = proto;
    return obj;
}

var foo = createObject(Foo.prototype);

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

Из приведенного выше рисунка мы можем найти, чтоfooобъект иFooЦепочка прототипов функций:

foo.__proto__ == Foo.prototype;
foo.__proto__.__proto__ == Foo.prototype.__proto__ == Object.prototype;
foo.__proto__.__proto__.__proto__ == Foo.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null;

Foo.__proto__ == Function.prototype;
Foo.__proto__.__proto__ == Function.prototype.__proto__;
Foo.__proto__.__proto__.__proto__ == Function.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null;

КонструкторFooЦепочка прототипов не имеетFoo.prototype, поэтому не может наследоватьFoo.prototypeсвойства и методы на . в то время как экземплярfooцепочка прототипов имеетFoo.prototype,следовательноfooможет быть унаследованFoo.prototypeсвойства и методы на .

На данный момент мы можем легко ответить на вопрос о детской обуви Xiaoying.FooЦепочка прототипов не имеетFoo.prototype, который не может быть унаследованFoo.prototypeВверхcombineNameметод, таким образом бросаяFoo.combineName is not a functionисключение. использоватьcombineNameметод, поэтомуFoo.prototype.combineName.call(this), или вот такthis.combineName()(thisк объекту экземпляра).

Добро пожаловать, чтобы следовать:Leechikit
Оригинальная ссылка:segmentfault.com

В конце статьи приветствуются вопросы и исправления. Писать оригинальные статьи непросто, если эта статья была вам полезна, ставьте лайки, рекомендуйте и подписывайтесь на автора для поддержки.