Автор оригинала: Mehran Hatami.
Это очень простой объектная модель на основе прототипов, которая была бы рассмотрена как образец во время объяснения, без комментариев:
function Person( name ){ this.name = name; } Person.prototype.getName = function(){ console.log( this.name ); } var person = new Person( 'George' );
Есть несколько важных точек, которые мы должны рассмотреть, прежде чем проходить через концепцию прототипа.
1- Как функции JavaScript на самом деле работают:
Чтобы сделать первый шаг, мы должны выяснить, как функции JavaScript на самом деле работают: как класс, как функция, используя это
Ключевое слово в нем или просто как обычная функция со своими аргументами. Кроме того, мы должны выяснить, что делает функция, и что она возвращается.
Допустим, мы хотим создать Человек
Объектная модель, но на этом шаге я буду пытаться Делайте то же самое, не используя Прототип
и Новый
ключевое слово . Отказ
Итак, на этом шаге Функции
, Объекты
и это
Ключевое слово все, что у нас есть.
Первый вопрос будет Как это
Ключевое слово может быть полезно без использования Новый
ключевое слово . Отказ
Итак, чтобы ответить на это, скажем, у нас есть пустой объект и две функции, такие как:
var person = {}; function Person( name ){ this.name = name; } function getName(){ console.log( this.name ); }
JavaScript имеет 3 разных способа использования этих функций без использования Новый
ключевое слово . Отказ
а. Позвоните в функцию в качестве обычной функции:
Person( 'George' ); getName(); //would print the 'George' in the console
В этом случае это
будет текущий объект контекста, который обычно является глобальным окно
объект в браузере или Глобальный
в Node.js
Отказ Это означает, что у нас было бы окно. Немейте в браузере или
Global.name в Node.js, с
«Джордж» как его ценность.
Стоит отметить, что запустил этот фрагмент кода в «Используйте строгий»
Режим предотвратит это
Ключевое слово, чтобы привязать к окно
объект в браузере или Глобальный
В Node.js. Вместо этого ценность это
будет undefined
Отказ Чтобы узнать больше о Строгий режим Посмотрите на этот пост: Строгий режим Отказ
б. Прикрепите функцию к объекту как его свойство
– Самый простой способ Чтобы сделать это, изменяя пустой человек
Объект, как:
person.Person = Person; person.getName = getName;
Таким образом, мы можем позвонить человеку, как:
person.Person( 'George' ); person.getName();// -->'George'
Теперь человек
Объект становится:
Object { Person: function, getName: function, name: 'George' }
– Другой способ прикрепить свойство к объекту использует Прототип
этого объекта, который можно найти в любом объекте JavaScript с именем __proto__
Отказ Я объясню это чуть позже в резюме, но что важно, мы можем получить аналогичный результат, делая:
person.__proto__.Person = Person; person.__proto__.getName = getName;
Однако мы на самом деле модифицируем Объект. Прототип
, потому что всякий раз, когда мы создаем объект JavaScript с использованием литералов ( {...}
), это создано на основе Объект. Прототип
Отказ Это означает, что он привязан к вновь созданному объекту как атрибут с именем __proto__
Так что, если мы изменим его, так как мы сделали на нашем предыдущем фрагменте кода, все объекты JavaScript будут изменены. Не очень хорошая практика. Так что же может быть лучшей практикой сейчас:
person.__proto__ = { Person: Person, getName: getName };
И теперь другие объекты в мире, но это все равно, похоже, не является хорошей практикой. Таким образом, у нас есть еще одно решение, но использовать это решение, мы должны вернуться к этой строке кода, где человек
Объект создан ( var person = {};
), а затем измените его как:
var propertiesObject = { Person: Person, getName: getName }; var person = Object.create( propertiesObject );
Что это делает, это создает новый JavaScript Объект
и прикрепляет PropertosmentObject
к __proto__
атрибут. Итак, чтобы убедиться, что это работает, вы можете сделать:
console.log( person.__proto__ === propertiesObject ); //true
Тем не менее, сложная точка здесь у вас есть доступ ко всем свойствам, определенным в __proto__
На первом уровне человек
объект (прочитайте резюме для более подробной информации).
Предупреждение : Во время поддержки Object.Prototype .__ Proto__
Уже сегодня существует сегодня в большинстве браузеров, его поведение было недавно стандартизировано только в новом спецификации Ecmascript 6. Если вам нужна поддержка браузеров Pre-ES6, рекомендуется только Object.getPrototyep ()
использоваться вместо этого.
Как вы видите, используя любой из этих двусторонних это
будет указывать на человек
объект.
с. Используйте вызов или применить, чтобы вызвать функцию
-
Применить ()
Метод вызывает функцию с даннымэто
значение и с аргументами, предусмотренными в качестве массива (или на массивом объекте).
а также
-
Звоните ()
Метод вызывает функцию с даннымэто
Значение и с аргументами при условии индивидуально.
Таким образом, что является моим любимым, так как мы можем легко вызвать наши функции, такие как:
Person.call( person, 'George' );
или же
//apply is more useful when params count is not fixed Person.apply( person, [ 'George' ]); getName.call( person ); getName.apply( person );
Эти 3 метода являются важными начальными шагами, чтобы выяснить .Прототип
Функциональность.
2- Как работает новое ключевое слово?
Понимание того, как Новый
Ключевое слово работает – второй шаг, чтобы понять .Прототип
Функциональность. Это то, что я использую для моделирования процесса:
function Person( name ){ this.name = name; } myPersonPrototype = { getName: function(){ console.log( this.name ); } };
В этой части я собираюсь взять все шаги JavaScript, принимает при использовании Новый
Ключевое слово, но я не собираюсь использовать Новый
Ключевое слово и Прототип
Отказ Так, когда мы делаем Новый человек («Джордж»)
, Человек
Функция служит конструктором, это то, что делает JavaScript, один на один:
а. Сделать пустой объект
JavaScript в основном делает пустой хеш, как:
var newObject = {};
б. Прикрепите все объекты прототипа к вновь созданному объекту
У нас есть MyPersonPrototype
Вот похоже на прототип объекта.
for( var key in myPersonPrototype ){ newObject[key] = myPersonPrototype[ key ]; }
Это не так, как JavaScript фактически прикрепляет свойства, которые определены в прототипе. Фактический способ связан с концепцией цепи прототипа.
Альтернатива шагам A & B:
Вместо того, чтобы сделать шаги A & B, вы можете получить тот же результат, делая:
var newObject = Object.create( myPersonPrototype ); //here you can check out the __proto__ attribute console.log( newObject.__proto__ === myPersonPrototype ); //true //and also check if you have access to your desired properties console.log( typeof newObject.getName );//'function'
Теперь мы можем позвонить в getname
функция в нашем MyPersonPrototype
:
newObject.getName();
с. Дать объекту конструктору,
Мы можем сделать это с нашим образцом, как:
Person.call( newObject, 'George' );
или же
Person.apply( newObject, [ 'George' ] );
Тогда конструктор может делать все, что он хочет, потому что это Внутри этого конструктора является объектом, который только что создал.
Этот конечный результат перед имитацией других этапов:
Object { name: 'George' }
Резюме:
В основном, когда вы используете Новый Ключевое слово на функцию, вы вызываете это, и эта функция служит конструктором, поэтому, когда вы говорите:
new FunctionName()
JavaScript внутренне делает объект, пустой хэш. Затем он дает этот объект конструктору, где конструктор может делать все, что он хочет, потому что это Внутри этого конструктора является объектом, который только что создал. Наконец, он дает вам этот объект, если вы не использовали оператор возврата в вашей функции, или если вы поместите возврат undefined;
в конце вашего функционального тела.
Поэтому, когда JavaScript посмотрит на поиск недвижимости на объекте, первое, что он делает, это выглядит на этом объекте. Тогда есть секретная недвижимость [[Прототип]]
, как правило, как __proto__
И что свойство – это то, что JavaScript смотрит на дальше. Кроме того, когда JavaScript просматривает __proto__
, насколько это снова еще один объект JavaScript, у него есть свой __proto__
атрибут. JavaScript идет вверх и вверх, пока не дойдет до того, как следующий __proto__
нулевой.
Объект. Прототип
единственный объект в JavaScript, где его __proto__
атрибут нулевой:
console.log( Object.prototype.__proto__ === null );//true
И вот как наследование работает в JavaScript.
Другими словами, когда у вас есть прототип свойства на функцию, и вы называете Новый
На этом, после того, как JavaScript заканчивается, глядя на этот вновь созданный объект для свойств, он пойдет посмотреть на функцию .Прототип
Отказ Таким образом, возможно, что этот объект имеет свой внутренний прототип и так далее.