Концепция наследования prototypal
является одной из самых сложных для многих разработчиков. Давайте попробуем понять корень проблемы, чтобы лучше понять prototypal inheritance
. Давайте начнем с функции plain
.
Если мы используем оператор new
в Tree function
, мы называем его функцией constructor
.
Каждая функция JavaScript
имеет prototype
. Когда вы регистрируете Tree.prototype
, вы получаете ...
Если вы посмотрите на вышеприведенный вывод console.log()
, вы также можете увидеть свойство конструктора в Tree.prototype
и свойство __proto__
, __proto__
представляет prototype
, на котором основан этот function
, и, поскольку это просто JavaScript function
без настройки inheritance
, это относится к Object prototype
, который является чем-то просто встроенным в JavaScript ...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
Это имеет такие вещи, как .toString, .toValue, .hasOwnProperty
и т. Д. ...
__proto__
, который был доставлен моей мозилле, устарел и заменен методом Object.getPrototypeOf
, чтобы получить object's prototype
.
Object.getPrototypeOf(Tree.prototype); // Object {}
Давайте добавим метод к нашему Tree
prototype
.
Мы изменили Root
и добавили в него ветку function
.
Это означает, что когда вы создаете instance
из Tree
, вы можете вызвать его метод branch
.
Мы также можем добавить primitives
или objects
к нашему Prototype
.
Давайте добавим child-tree
к нашему Tree
.
Здесь Child
наследует свой prototype
из дерева, что мы делаем здесь, используя метод Object.create()
для создания новый объект, основанный на том, что вы передаете, вот он Tree.prototype
. В этом случае мы устанавливаем прототип Child для нового объекта, который выглядит идентично прототипу Tree
. Далее мы устанавливаем Child's constructor to Child
, если мы этого не сделаем, это будет указывать на Tree()
.
Child
теперь имеет свой собственный prototype
, его __proto__
указывает на Tree
и Tree's prototype
указывает на основание Object
.
Child
|
\
\
Tree.prototype
- branch
|
|
\
\
Object.prototype
-toString
-valueOf
-etc., etc.
Теперь вы создаете instance
из Child
и вызываете branch
, который первоначально был доступен в Tree
. На самом деле мы не определили наш branch
на Child prototype
. НО, в Root prototype
, от которого наследует Child.
В JS все не является объектом, все может действовать как объект.
Javascript
имеет такие примитивы, как strings, number, booleans, undefined, null.
Они не object(i.e reference types)
, но, безусловно, могут действовать как object
. Давайте рассмотрим пример здесь.
В первой строке этого списка строковому значению primitive
присваивается имя. Вторая строка обрабатывает имя как object
и вызывает charAt(0)
с использованием точечной нотации.
Вот что происходит за кулисами: // что делает движок JavaScript
String object
существует только за один оператор до его уничтожения (процесс под названием autoboxing
). Давайте снова вернемся к нашему prototypal
inheritance
.
Javascript
поддерживает наследование через delegation
на основе prototypes
. Function
имеет свойство prototype
, которое относится к другому объекту. properties/functions
просматриваются из самого object
или через цепочку prototype
, если он не существует A prototype
в JS - это объект, который yields
указывает вам на родитель другого object
. [то есть .. делегирование] Delegation
означает, что если вы не в состоянии что-то сделать, вы скажете кому-то другому сделать это для вас.
https://jsfiddle.net/say0tzpL/1/
Если вы посмотрите вверх выше скрипки собака имеет доступ к методу toString
, но в нем его нет, но доступны через цепочку прототипов, которая делегирует Object.prototype
Если вы посмотрите на приведенную ниже, мы пытаемся получить доступ к call
метод, который доступен в каждом function
.
https://jsfiddle.net/rknffckc/
Если вы посмотрите вышеупомянутую скрипку , Profile
Функция имеет доступ к методу call
, но недоступна в нем, но доступна через цепочку прототипов, которая делегирует Function.prototype
Примечание: prototype
является свойством конструктора функции, тогда как __proto__
является свойством объектов, созданных из конструктора функции. Каждая функция имеет свойство prototype
, значение которого является пустым object
. Когда мы создаем экземпляр функции, мы получаем внутреннее свойство [[Prototype]]
или __proto__
, ссылка на который является прототипом функции constructor
.
Вышеприведенная диаграмма выглядит немного сложнее, но дает полную картину того, как работает prototype chaining
. Давайте медленно пройдемся по этому: 11100] и Foo
https://jsfiddle.net/kbp7jr7n/
Если вы посмотрите код выше, у нас есть конструктор Foo
, у которого есть метод identify()
и конструктор Bar
, у которого есть метод speak
. Мы создаем два экземпляра Bar
b1
и b2
, родительский тип которых Foo
. Теперь, вызывая метод speak
из Bar
, мы можем определить, кто вызывает речь, по цепочке prototype
.
Bar
теперь имеет все методы Foo
, которые определены в его prototype
. Давайте углубимся в понимание Object.prototype
и Function.prototype
и как они связаны. Если вы посмотрите конструктор Foo
, Bar
и Object
- это Function constructor
.
prototype
в Bar
- это Foo
, prototype
в Foo
- Object
, и если вы посмотрите внимательно prototype
из Foo
относится к Object.prototype
.
Прежде чем мы закроем это, давайте просто завернем небольшой фрагмент кода здесь, чтобы суммировал все выше . Мы используем здесь оператор instanceof
, чтобы проверить, имеет ли object
в своей цепочке prototype
свойство prototype
для constructor
, которое ниже суммирует всю большую диаграмму.
Я надеюсь, что это дополнение немного информации, я знаю, что это может быть большим, чтобы понять ... в простых словах его это просто объекты, связанные с объектами !!!!
Основное преимущество состоит в том, что когда вы работаете с реальным вызываемым объектом, вы можете делать такие вещи, как применять к нему декораторы в URLConf. Таким образом, вы можете делать такие вещи, как:
from django.conf.urls.defaults import *
from django.contrib.auth.decorators import login_required
from some_module import some_view
urlpatterns = patterns('',
(r'^some_url/$', some_view),
(r'^some_other_url/$', login_required(some_view)))
и т. Д.
Это позволяет вам иметь декораторы, которые применяются к представлению только тогда, когда вы этого хотите, вместо того, чтобы украшать файл представлений и затем жить с ним, всегда имея этот декоратор применил.
Просмотр источника в RegexURLPattern (который используется под обложками defaults.url
) подтверждает, что импорт происходит только тогда и при необходимости. , так что ваши идеи верны: это небольшая оптимизация, но требует тщательного тестирования!