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