Недавно я смотрю "JavaScript Advanced Programming" (второе издание)
Создание объектов в JavaScript
• Фабричный режим
• Режим конструктора
• Прототип режим
• Объединение конструктора и схемы прототипа
• Прототип динамический режим
Большинство объектно-ориентированных языков имеют концепцию класса, посредством которой могут быть созданы несколько объектов с одинаковыми методами и атрибутами. Хотя технически, JavaScript является объектно-ориентированным языком, JavaScript не имеет концепции классов, все является объектом. Любой объект является экземпляром определенного эталонного типа и создается с помощью существующих ссылочных типов; Справочный тип может быть собственным или настроенным. Нативными типами эталон: объект, массив, данные, regexp, функция. ! Справочный тип - это структура данных, которая организует данные и функции вместе, обычно называемые классом. В JavaScript, которому не хватает концепции класса, проблема, которую необходимо решить, заключается в том, как эффективно создавать объекты.
1.1.0. Общие методы создания объектов
var person = {}; // объектное буквальное представление эквивалентно var person = new objcect (); Person.name = 'Evansdiy'; Person.age = '22'; Person.Friends = ['ajiao', 'tiantian', 'pangzi']; Person.logname = function () {console.log (this.name);}На основе типа ссылки объекта создается объект, который содержит четыре свойства, одним из которых является метод. Если вам понадобится много случаев, таких как человек, будет много дублированного кода.
1.1.1. Заводская модель
Создайте объект с функцией, которая может содержать детали объекта, а затем вернуть объект.
Функциональный человек (имя, возраст, друзья) {var o = {имя: имя, возраст: возраст, друзья: друзья, logname: function () {console.log (this.name); }}; вернуть o;} var person1 = person ('evansdiy', '22', ['ajiao', 'tiantian', 'pangzi']);Каждый раз, когда вызывается функция человека, новый объект создается через объект o внутри функции, а затем возвращается. Кроме того, этот внутренний объект o существует для создания нового объекта, не имеет никакой другой цели. Кроме того, невозможно определить тип объекта, созданный заводским режимом.
1.1.2. Режим конструктора
Функция человека (имя, возраст, задание) {this.name = name; this.age = возраст; this.job = job; this.logname = function () {console.log (this.name); }} // Создать экземпляр человека через нового оператора var person1 = new Person ('boy-a', '22', 'keormer'); var person2 = new Person ('Girl-b', '23', 'учитель'); person1.logname (); //boy-aperson2.logname (); // Girl-AСравнивая заводский режим, мы можем обнаружить, что здесь нет необходимости создавать промежуточные объекты, возврата нет. Кроме того, экземпляр конструктора может быть идентифицирован как конкретный тип, который решает проблему распознавания объектов (путем проверки атрибута конструктора экземпляра или использования оператора экземпляра, чтобы проверить, создается ли экземпляр конструктором).
console.log (person1.constructor == Person); // Конструктор находится в прототипе конструктора и указывает на конструктор, и результат верен
console.log (extram1 person); // Использование оператора экземпляра, чтобы определить, является ли Person1 экземпляром конструктора, но шаблон конструктора также имеет свои проблемы. Фактически, метод logname будет воссоздан один раз в каждом экземпляре. Следует отметить, что методы, создаваемые экземплярами, не равны, а следующий код получит ложные:
console.log (person1.logname == person2.logname); // false Мы можем переместить метод за пределами конструктора (измененный в глобальную функцию) для решения этой проблемы:
function logname () {console.log (this.name);} function logage () {console.log (this.age);}Тем не менее, глобальные функции, созданные во всем мире, могут быть вызваны только случаями, созданными человеком, что немного нереально; Если есть много методов, их все равно нужно определить один за другим, не имея инкапсуляции.
1.1.3. Прототип режим
Каждая функция в JavaScript содержит указатель на атрибут прототипа (большинство браузеров могут получить к нему доступ через внутренний атрибут __proto__), атрибут прототипа - это объект, который содержит свойства и методы, разделяемые всеми экземплярами, созданными определенным типом ссылки.
function person () {} person.name = 'evansdiy'; person.prototype.friends = ['ajiao', 'jianjian', 'pangzi']; person.prototype.logname = function () {console.log (this.name);} var person1 = new Person1 ();Приведенный выше код делает эти вещи:
1. Определите конструктора. Человек автоматически получает свойство прототипа. Это свойство содержит только свойство конструктора, указывающее на человека по умолчанию;
2. Добавьте три атрибута через Person.prototype, один из которых используется в качестве метода;
3. Создайте экземпляр человека, а затем вызовите метод logName () на экземпляре. !
Что вам нужно отметить, так это процесс вызова метода logname ():
1. Посмотрите метод LogName () на экземпляре Person1 и обнаружил, что такого метода нет, поэтому я отсоединялся до прототипа Person1
2. Ищите метод Logame () на прототипе Person1. Есть этот метод. Таким образом, мы называем этот метод на основе такого процесса поиска. Мы можем помешать экземпляру получить доступ к одному атрибуту имени на прототипе, определив тот же атрибут имени в прототипе на экземпляре. Следует отметить, что это не удалит тот же наименимый атрибут на прототипе, но будет только предотвратить доступ к экземпляру.
var person2 = new Person ();
Person2.name = 'laocai'; Если нам больше не нужны свойства на экземпляре, мы можем удалить его через оператор Delete.
delete person2.name; Используйте цикл для перечисления всех атрибутов, к которым может получить доступ экземпляр (независимо от того, существует ли атрибут в экземпляре или в прототипе):
для (i on person1) {console.log (i);}В то же время вы также можете использовать метод hasownproperty (), чтобы определить, существует ли определенное свойство на экземпляре или в прототипе. Только когда свойство существует в экземпляре, будет возвращено:
console.log (person1.hasownproperty ('name')); // true! HasownProperty происходит от прототипа объекта и является единственным способом в JavaScript, чтобы не искать цепочку прототипа при обработке свойств. [через JavaScript Secret Garden] Кроме того, вы также можете использовать метод in operator и hasownproperty (), чтобы определить, существует ли определенное свойство в экземпляре или в прототипе:
console.log ((«Друзья» в личности1) &&! Person1.hashownproperty ('друзья')); сначала определить, может ли Person1 получить доступ к собственности Friends. Если возможно, тогда определите, существует ли это свойство в экземпляре (обратите внимание на предыдущее!). Если его не существует в экземпляре, это означает, что это свойство существует в прототипе. Как упоминалось ранее, прототип также является объектом, поэтому мы можем написать прототип, используя объектное буквальное представление. Предыдущий метод написания кода в прототип может быть изменен на:
Person.prototype = {name: 'Evansdiy', друзья: ['ajiao', 'jianjian', 'pangzi'], logname: function () {console.log (this.name); }}Поскольку литеральный синтаксис объекта переписывает весь прототип прототипа, атрибут конструктора, полученный по умолчанию при создании конструктора, будет указывать на конструктор объекта:
// после того, как объект буквально переписывает прототип
console.log (person1.constructor); // Объект, однако, оператор экземпляра все равно вернет желаемый результат:
// после того, как объект буквально переписывает прототип
console.log (extram1 person); // true, конечно, вы можете вручную установить значение конструктора в прототипе для решения этой проблемы.
Person.prototype = {Constructor: Person, ......}Если объект прототипа изменен после создания экземпляра объекта, модификация прототипа будет немедленно отражена во всех экземплярах объекта:
Функция Person () {}; var person1 = new Person (); person.prototype.name = 'evansdiy'; console.log (person1.name); // 'evansdiy'Связь между экземпляром и прототипом является просто указателем, а не копией прототипа. Прототип на самом деле является процессом поиска. Любые модификации, внесенные в объект прототипа, будут отражены во всех экземплярах объектов, даже если прототип изменен после создания экземпляра. Что если объект прототипа переписывается после создания экземпляра объекта?
function person () {}; var person1 = new Person1 (); // Созданный экземпляр относится к первоначальному прототипу // прототип Person.prototype = {Friends: ['ajiao', 'jianjian', 'pangzi']} var person2 = new Person (); // этот экземпляр ссылается на новый прототип. console.log (person1.friends);Приведенный выше код будет иметь неопределенную ошибку, когда она будет выполнена до последней строки. Если мы используем для перечисления доступных свойств в личности1, мы обнаружим, что внутри нет ничего, но Person2 может получить доступ к атрибуту друзей на прототипе. ! Переписывание прототипа отключает связь между существующим прототипом и всеми экземплярами объекта, созданными ранее. Прототип экземпляра объекта, созданного ранее, все еще существует, но он старый.
// При создании человека1 объект прототипа еще не был переписан. Следовательно, конструктор в объекте прототипа по -прежнему остается по умолчанию Console.log (person1.constructor); // person () //, но конструктор Person2 указывает на object () console.log (person2.constructor); // Object ()
Следует отметить, что шаблон прототипа игнорирует процесс передачи параметров для конструктора, и все экземпляры получают одинаковое значение атрибута. В то же время существует большая проблема с шаблоном прототипа, то есть значение типа эталонного типа в объекте прототипа будет передаваться всеми экземплярами, и изменение значения типа эталон также будет отражена во всех экземплярах объекта.
function Person () {}; Person.prototype = {Friends: ['ajiao', 'tiantian', 'pangzi']} var person1 = new Person (); var person2 = new Person (); person1.fushs.push ('laocai'); консоль.Изменение значения типа ссылки Person1 Friends означает, что друзья в лице 2 также изменится. На самом деле, друзья, сохраненные в прототипе, на самом деле являются просто указателем на значение друзей в куче (длина этого указателя фиксируется и сохраняется в стеке). Когда экземпляр получает доступ к значению типа ссылки через прототип, к нему также доступ к указателю вместо того, чтобы получить доступ к копии в соответствующем экземпляре (такую копию не существует).
1.1.4. Создать объекты в сочетании с конструктором и шаблоном прототипа
Объединяя преимущества конструктора и режима прототипа, составляя их соответствующие недостатки, используя конструкторы для прохождения параметров инициализации, определить атрибуты экземпляра в них и использование прототипов для определения общих методов и публичных атрибутов. Этот режим наиболее широко используется.
Функция человека (имя, возраст) {this.name = name; this.age = возраст; this.friends = ['ajiao', 'jianjian', 'pangzi'];} person.prototype = {constructor: person, logname: function () {console.log (this.name); }} var person1 = new Person ('evansdiy', '22'); var person2 = new Person ('amy', '21'); person1.logname (); // 'evansdiy'person1.friends.push (' haixao '); console.log (person2.friends.length); // 31.1.5. Динамический режим прототипа
Динамический режим прототипа инкапсулирует всю необходимую информацию в конструктор, и использует оператор IF, чтобы определить, существует ли определенное свойство в прототипе. Если его не существует (когда конструктор вызывает впервые), выполните код инициализации прототипа внутри оператора IF.
Функция человека (имя, возраст) {this.name = name; this.age = возраст; if (typeof this.logname! = 'function') {person.prototype.logname = function () {console.log (this.name); }; Person.prototype.logage = function () {console.log (this.age); }; }; };} var person1 = new Person ('evansdiy', '22'); // Конструктор был вызван впервые, и прототип был изменен в это время. var person2 = new Person ('amy', '21'); // метод logname () уже существует, и прототип больше не будет измененСледует отметить, что этот шаблон не может использовать литеральный синтаксис объекта для написания объектов прототипа (это будет переопределять объекты прототипа). Если прототип переписывается, объект прототипа, доступный для первого экземпляра, созданного конструктором, не будет содержать свойства объекта прототипа в операторе IF.
Функция человека (имя, возраст) {this.name = name; this.age = возраст; if (typeof this.logname! = 'function') {person.prototype = {logname: function () {console.log (this.name); }, logage: function () {console.log (this.age); }}}};} var person1 = new Person ('evansdiy', '22'); var person2 = new Person ('amy', '21'); person2.logname (); // 'amy'person1.logname (); // logname () Метод не существуетСледует отметить, что у каждой модели есть свои сценарии приложения, и это не имеет значения его преимуществ и недостатков.
Приведенный выше анализ различных моделей создания объектов в JavaScript - это весь контент, которым я делюсь с вами. Я надеюсь, что это может дать вам ссылку, и я надеюсь, что вы сможете поддержать Wulin.com больше.