Что такое прототип
Тип функции имеет прототип свойств, который переводится непосредственно в прототип. Это свойство является указателем, указывающим на объект, который содержит некоторые свойства и методы, которые будут переданы всеми экземплярами (объектами), генерируемыми текущей функцией.
Исходя из того, что было сказано ранее, вы можете получить следующий код:
function person () {...} person.prototype = {country: 'china', sayname: function () {...}}Во -первых, создается человеческий тип функции экземпляра, а затем прототип метода человека является объектом, и объявление указывает на объект. Свойства и методы в этом объекте будут переданы экземпляром, сгенерированным текущей функцией человека. То есть:
Person1 = новый человек (); Person2 = новый человек ();
Person1 и Person2 снова генерируются через экземпляры типа функции человека. Оба имеют общую страну собственности и метод SayName, потому что все они имеют указатель (__proto__), указывая непосредственно на объект, на который указывается Person.prototype. Однако обратите внимание, что указатель __proto__ не является стандартным. Это определяется только браузерами, такими как Chrome и Firefox. На самом деле, это свойство не будет использоваться, но используется только как понимание прототипа:
Что касается использования прототипов и других методов, мы поговорим об этом более конкретно позже.
Создать шаблон объекта
Далее, давайте посмотрим на методы и общие закономерности для создания объектов, а также их преимущества и недостатки.
1. Заводская модель
Так же, как и фабрика, процесс создания конкретных объектов абстрагируется, и функции используются для инкапсуляции деталей создания объектов с конкретными интерфейсами. Используя функции вместо частичного повторения, код выглядит следующим образом:
Функция CreatePerson (имя, возраст, задание) {var O = new Object (); o.name = name; o.age = возраст; o.job = job; o.sayname = function () {alert (this.name); }; return o;} var person1 = createperson ("jiangshui", "22", "инженер");Это создает человека, а заводской шаблон решает проблему повторного создания нескольких подобных объектов, но не решает проблему распознавания объекта. Просто создается объект, и независимо от того, создан ли этот объект из человеческого шаблона или шаблона животных, невозможно различить тип этого объекта.
2. Режим конструктора
Создайте пользовательский конструктор для определения свойств и методов пользовательских типов объектов.
Функция человека (имя, возраст, задание) {this.name = name; this.age = возраст; this.job = jpb; this.sayname = function () {alert (this.name); };}; var person1 = новый человек (...);3. Разница между режимом конструктора и заводским режимом:
Человек является объектом типа функции. После нового объект будет продолжать генерироваться. Однако, поскольку этот недавно сгенерированный объект передается в функции и назначен этому указателю, переданное содержание становится свойством или методом вновь сгенерированного объекта.
Привычка конструкторов по умолчанию заглавляется в первой букве. Вышеуказанное выполнение кода проходит следующие шаги:
В случаях, сгенерированных таким образом, все они содержат атрибут конструктора по умолчанию, указывающий на функцию конструктора, например:
предупреждение (Person1.constructor == Person);
Следовательно, используя шаблон конструктора, существует различие типа, и его экземпляр может быть идентифицирован как конкретный тип.
Кроме того, конструктор является обычной функцией. Поскольку вы хотите отзыв, чтобы получить новый объект, вы используете новый, чтобы назвать его. Если нет, выполнение его напрямую похоже на нормальную функцию. Например, если вы выполняете Person.sayname () выше, window.name появится, потому что функция выполняется под окном, поэтому эта точка в окне.
Режим конструктора также ошибочен. Методы в режиме конструктора воссозданы в каждом экземпляре, поэтому функции одного и того же имени в разных случаях не равны. Например:
Person1.sayname == Person2.sayname; //ЛОЖЬ
То есть каждый экземпляр объекта, атрибуты и методы, генерируемые конструктором, являются уникальными и копируются. Атрибуты уникальны, потому что это именно то разница между объектами, но многие методы имеют одинаковые функции и код. Если вы копируете их неоднократно много раз, вы, очевидно, будете тратить ресурсы.
Таким образом, мы можем поместить функцию снаружи, а затем указать на функцию с указателем в конструкторе. В сгенерированном экземпляре метод хранит указатель на определенную функцию, что означает общую функцию:
Функция человека (имя, возраст) {this.name = name; this.age = возраст; this.sayname = sayname;} function showername () {alert (this.name);}Однако, таким образом, эта функция становится глобальной функцией, и она не сильно коррелирует с конструктором человека и не имеет инкапсуляции.
Далее, пожалуйста, приходите в режим прототипа.
Прототип режим
Часть оснований о прототипах была введена ранее. Проще говоря, каждая функция имеет атрибут прототипа, указывающий на объект (объект прототипа), и некоторые свойства или методы могут быть размещены в этом объекте. Тогда экземпляр, сгенерированный этой функцией, будет иметь нерегулярное атрибут (__proto__), указывающий на прототип.
С этой точки зрения, вы должны быть в состоянии понять, что свойства и методы, генерируемые прототипом, передаются всеми экземплярами.
Это просто решает проблему совместного использования функций в приведенном выше режиме конструктора и в примерах. Например, следующий код:
function person () {....} person.prototype.name = "jiangshui"; person.prototype.sayname = function () {alert (this.name);}; var person1 = new Person (); Person1.sayname (); // Цзяншуиили
Person.prototype = {Constructor: Person, имя: "jiangshui", sayname: function () {alert (this.name); }};Второй метод охватывает весь объект прототипа, поэтому вам необходимо вручную указать свойство конструктора, указывая на функцию конструктора, в противном случае он будет указывать на объект.
Давайте разберемся с их отношениями:
Используйте isprototypeof () для определения взаимосвязи между объектами. Например:
Person.prototype.isprototypeof (person1);
Когда код считывает определенное свойство объекта, будет выполнен поиск. Начните с текущего объекта, а если нет, ищите объект прототипа, на который указан указатель, без поиска конструктора. Доступ к экземпляру объекта может быть доступен, но не может переопределить значение объекта прототипа. Если атрибут с тем же именем, что и объект прототипа, установлен в экземпляре, процесс поиска заканчивается в экземпляре без доступа к объекту прототипа, поэтому достигается цель перезаписания. Следовательно, даже если это свойство установлено на NULL, это означает, что свойство уже существует в экземпляре, и свойство не будет отменено, так что можно получить соответствующее свойство прототипа.
Поэтому вам необходимо использовать оператор Delete для полного удаления атрибутов экземпляра, чтобы можно было пересмотреть прототип.
Прототип является динамическим, и любые модификации, сделанные в объект прототипа, могут быть немедленно отражены из экземпляра. Причина - это неразрывная связь между экземпляром и прототипом. Каждый раз, когда называется метод свойства экземпляра, будет проведен запрос. Если прототип изменится, результат запроса также изменится.
После понимания прототипа мы также можем добавить новые методы или атрибуты в собственный объект. Нативные ссылочные типы, такие как объект, массив, строка и т. Д., Аналогичны конструкторам выше. Мы можем использовать прототип для расширения их методов. Например:
String.prototype.startswith = function (text) {return this.indexof (text) == 0;}; var msg = "hello world"; msg.startswith ("hello");Этот код добавляет метод StartSwith к нативной строке типа ссылки, которая должна передавать параметр, чтобы увидеть, начинается ли строка, которая будет проверена с параметра. Из -за динамического характера прототипа все переменные типа строки получают этот метод, выполнив его.
Однако этот метод не рекомендуется. Если вы используете слишком много и слишком много кода, это приведет к трудностям в обслуживании, путанице в коде и т. Д. Вообще говоря, сначала будет унаследован собственный тип ссылки, а затем создан на недавно настроенном типе. Что касается наследства, мы рассмотрим его позже.
Паттерн прототипа тоже не всемогущий. Все атрибуты и методы в прототипе разделяются во всех случаях, поэтому он очень подходит для функций и других функций, но для атрибутов, содержащих ссылочные типы, возникают некоторые конфликты. Например:
function person () {} person.prototype = {Constructor: Person, друзья: ["greg", "jack"]}; var person1 = new Person (); var person2 = new Person (); person1.friends.push ("tom"); console.log (person2.friends);В консоли вы увидите, что есть дополнительный Том для друзей2, что я не хочу, а при определении своего друга на Person1, это влияет на экземпляр Person2.
Таким образом, нам нужно использовать его в сочетании с шаблоном прототипа и шаблоном конструктора.
Используйте режим конструктора и режим прототипа в комбинации
Это наиболее часто используемый шаблон. Конструктор используется для определения свойств экземпляра и настройки путем передачи параметров; Прототип используется для определения методов или атрибутов, которые требуют совместного использования всех экземпляров. Таким образом, настройка достигается, обеспечивается обмен, и проблемы избегаются.
Функция человека (имя, возраст, задание) {this.name = name; this.age = возраст; this.job = job; this.friends = ["greg", "jack"];} person.prototype = {Constructor: Person, sayName: function () {alert (this.name); }}; var jiangshui = новый человек ("Jiangshui", "22", "Инженер");Практические примеры применения
Хорошо, здесь вы можете понять, что такое прототип и как создавать объекты, но каково их использование? Действительно, моя предыдущая работа заключалась в том, чтобы написать какой -то код, используя jQuery, и я не мог использовать инкапсуляцию, а затем генерировать объекты для реализации функций и т. Д. Так каковы их использование?
Этот метод разработки в основном используется для модульной и сборочной разработки. Например, всплывающая функция, которую вы часто используете, конечно, вы можете вставлять и копировать всплывающий код каждый раз, а затем изменять его и использовать его в проекте. Лучшим выбором является абстрактно инкапсулировать ваш код функции всплывающего окна в такой компонент, чтобы, когда вам нужно использовать всплывающие окна, вам нужно только передать параметры для генерации всплывающего экземпляра, и вы можете его позвонить.
Прототип объектов и цепочек прототипа
В JavaScript все является объектом, но есть также различия в объектах. Он может быть примерно разделен на две категории, а именно: обычные объекты (объект) и функциональные объекты (функция).
Вообще говоря, объекты, генерируемые через новую функцию, являются объектами функции, а другие объекты являются обычными объектами.
Приведите пример:
функция f1 () {// todo} var f2 = function () {// todo}; var f3 = new function ('x', 'console.log (x)'); var o1 = {}; var o2 = new object (); var o3 = new f1 (); console.log (typeof f1, // функция typeof f2, // функция typeof f3, // функция typeof o1, // объект typeOf o2, // type objF1 принадлежит к объявлению функции. Наиболее распространенным способом определения функции является то, что F2 на самом деле является анонимной функцией. Назначьте эту анонимную функцию F2, который принадлежит к выражению функции. F3 не распространен, но это также функциональный объект.
Функция - это объект, который поставляется с JS. Когда F1 и F2 создаются, JS автоматически создаст эти объекты через New Function (). Следовательно, эти три объекта создаются с помощью New Function ().
Есть два способа создания объектов в JavaScript: объектные литералы и новые выражения. Создание O1 и O2 просто соответствует этим двум способам. Давайте сосредоточимся на O3. Если вы используете идеи Java и C# для понимания, O3 является объектом экземпляра F1, а O3 и F1 - один и тот же тип. По крайней мере, я так думал, но это не ...
Так как вы это понимаете? Это очень просто. Посмотрите, генерируется ли O3 через новую функцию. Очевидно, нет. Поскольку это не функциональный объект, это обычный объект.
После простого понимания объектов функций и обычных объектов давайте узнаем о прототипах и цепях прототипа в JavaScript:
В JS, всякий раз, когда создается функциональный объект F1, некоторые свойства встроены в объект, включая прототип и __proto__, прототип является объектом прототипа, который записывает некоторые свойства и методы F1.
Следует отметить, что прототип невидим для F1, то есть F1 не будет искать свойства и методы в прототипе.
function f () {} f.prototype.foo = "abc"; console.log (f.foo); //неопределенныйИтак, что такое использование прототипа? Фактически, основной функцией прототипа является наследование. С точки зрения непрофессионала, свойства и методы, определенные в прототипе, остаются для их «потомков», поэтому подклассы могут полностью получить доступ к свойствам и методам в прототипе.
Чтобы узнать, как F1 оставляет прототипы для «потомков», нам нужно понять цепочку прототипа в JS. В настоящее время __proto__ в JS вышел на рынок. Этот парень очень странный и скрытый, так что вы часто не видите его, но он существует как в обычных объектах, так и в функциональных объектах. Его функция состоит в том, чтобы сохранить объект прототипа родительского класса. Когда JS создает объект через новое выражение, он обычно присваивает прототип родительского класса атрибуту __proto__ нового объекта, который образует поколение наследования ...
function f () {} f.prototype.foo = "abc"; var obj = new f (); console.log (obj.foo); // ABCТеперь мы знаем, что __proto__ в OBJ спасает прототип F, так что сохраняется в __proto__ в прототипе F? Смотрите следующую картинку:
Как показано на рисунке, объект. Прототип, хранящийся в __proto__ из F.Prototype, а также __proto__ в объекте. Как показано на рисунке ниже:
После того, как у объекта OBJ есть такая цепочка прототипа, когда obj.foo выполняется, OBJ сначала обнаружит, есть ли у него атрибут, но не найдет свой собственный прототип. Когда Фу не может быть найден, OBJ будет искать по очереди по цепочке прототипа ...
В приведенном выше примере мы определяем атрибут Foo на прототипе F, а затем OBJ найдет этот атрибут в цепочке прототипа и выполняет его.