Курсовая работа (проект) Курстық жұмыс (жоба) тақырыбы Тема курсовой работы (проекта) Разработка сайта об автомобилях с помощью JavaScript



бет4/7
Дата30.04.2024
өлшемі65.5 Kb.
#500219
түріКурсовая
1   2   3   4   5   6   7
Лесбек Әділет курсавой

2 Практическая часть


2.1 Интернет-магазины в сфере автомобильного бизнеса, их функционал

Будьте очень осторожны при работе с изменяемыми свойствами. Если вы хотите увеличить значение AnotherObject.a, единственный правильный способ — это elseObject.a++.


На этом этапе у вас может возникнуть вопрос: почему один объект должен ссылаться на другой объект? Каковы реальные преимущества? Это очень правильный вопрос, но чтобы полностью понять и оценить, что это такое и насколько он полезен, мы должны сначала понять, чем [[Прототип]] не является.
Как мы объясняли в главе 4, в JavaScript нет абстрактных моделей/диаграмм для объектов, называемых классами, как в классо-ориентированных языках. В JavaScript есть только объекты.
На самом деле, JavaScript почти уникален среди языков, возможно, единственный язык, который имеет право использовать ярлык «объектно-ориентированный», поскольку это один из очень короткого списка языков, где вы можете создать объект напрямую, без класса. совсем.
В JavaScript классы не могут описать, что может делать объект (их не существует!). Объект напрямую определяет свое поведение. Есть только объект.
«Классовые» функции
В JavaScript есть особый тип поведения, который годами бессовестно использовался для разрушения того, что выглядит как классы. Мы рассмотрим этот подход подробно.
Своеобразное поведение «типа класса» связано со странной спецификацией функций: все функции по умолчанию имеют общедоступное, неперечисляемое (см. главу 3) свойство, называемое прототипом, которое представляет произвольный объект:
функция Foo() { // ...
}
Фу.прототип; // {}
Этот объект часто называют прототипом Foo, поскольку, к сожалению, мы получаем к нему доступ через ссылку Foo.prototypeproperty. Однако эта терминология сбивает нас с толку, как мы вскоре увидим. Вместо этого я называю его «объектом, ранее известным как прототип Фу». Просто шучу. Как насчет «Прототипа объекта с произвольной маркировкой опорной точки»?
Самый простой способ объяснить это состоит в том, что каждый объект, созданный в результате нового вызова Foo() (см. главу 2), в конечном итоге связывается (несколько произвольно) с этим объектом «прототип точки Foo».
Давайте покажем:
функция Foo() { // ...
}
вар а = новый Foo();
Object.getPrototypeOf(a) === Foo.prototype; // настоящий
Когда a создается путем вызова new Foo(), одна из вещей, которая происходит (см. все четыре шага в главе 2), заключается в том, что a получает внутреннюю ссылку [[Proto type]] на объект, представленный Foo.prototype.
Остановитесь на минутку и подумайте о последствиях этого утверждения.
В классо-ориентированных языках вы можете создавать несколько копий (других экземпляров) класса, например, выдавливая что-то из формы. Как мы видели в главе 4, это происходит потому, что процесс создания (или наследования) класса означает «перенос плана поведения из этого класса на физический объект», и это повторяется для каждого нового экземпляра.
Но JavaScript не выполняет такие операции копирования. Вы не создаете несколько экземпляров класса. Вы можете создать несколько объектов, связанных с [[Prototype]], для одного общего объекта. Но по умолчанию копирование не производится, поэтому эти объекты не полностью отделены и не отключены друг от друга, а вполне связаны.
new Foo() приводит к созданию нового объекта (мы назвали его a), и этот новый объект a внутренне связан с объектом Foo.prototype.
В итоге мы получили два связанных объекта. Вот и все. Мы не открывали класс. Мы, конечно, не копировали поведение «класса» на реальный объект. Мы только что связали два объекта вместе.
На самом деле секрет, который скрывает большинство JS-разработчиков, заключается в том, что новая функция Foo() не имеет прямого отношения к процессу обращения. Это был случайный побочный эффект. new Foo() — это косвенный, обходной способ получить то, что мы хотим: новый объект, привязанный к другому объекту.
Можем ли мы получить то, что хотим, прямым путем? Да! Символ — Object.create(..). Но мы вернемся к этому немного позже.
В JavaScript мы не копируем данные из одного объекта («класса») в другой («экземпляр»). Мы устанавливаем связи между объектами. У механизма стрелки визуально движутся справа налево и снизу вверх.
Этот механизм часто называют прототипическим наследованием (вскоре мы рассмотрим код более подробно), который обычно представляет собой динамическую языковую версию классического наследования. Это попытка следовать общему пониманию того, что означает «наследование» в классно-ориентированном мире, но изменить (читай: наложить) понимаемую семантику, чтобы она соответствовала динамическому сценарию.
Слово «наследование» имеет очень сильное значение и имеет множество прецедентов. Простое добавление слова «прототип» перед ним, чтобы отличить практически противоположное поведение в JavaScript, избавило от путаницы почти на два десятилетия.
Я бы сказал, что поставить слово «прототип» перед словом «наследие» — это все равно, что держать апельсин в одной руке и яблоко в другой и требовать, чтобы яблоко называлось «красным апельсином», и фундаментально менять его истинное значение. Какой бы непонятный ярлык я ни навесил перед ним, это не меняет того факта, что один фрукт — яблоко, а другой — апельсин.
Лучше всего говорить яблоки яблокам, используя максимально точную и прямую терминологию. Это облегчает понимание их сходств и многих различий, поскольку у нас есть простое и общее понимание того, что означает «яблоко».
Из-за путаницы и путаницы в терминах я верю в сам ярлык «наследование прототипа» (и стараюсь не применять неправильно всю связанную с ним классо-ориентированную терминологию, такую ​​​​как «класс», «структура» или «экземпляр». полиморфизм» и т. д.) Это принесло больше вреда, чем пользы, объясняя, как на самом деле работает движок JavaScript.
Наследование относится к копированию поведения, тогда как JavaScript не копирует свойства объекта (по умолчанию). Вместо этого JS создает связь между двумя объектами, где один объект может обеспечивать связь свойства/функции с другим объектом. Хорошо легирование — более точный термин для обозначения механизма привязки объектов JavaScript.
Другой термин, который иногда часто используется в JavaScript, — это дифференциальное наследование. Идея здесь состоит в том, чтобы описать поведение объекта с точки зрения того, чем оно отличается от более общего дескриптора. Например, вы объясняете, что автомобиль — это тип транспортного средства, но имеет ровно четыре колеса, а не переописываете все характеристики, составляющие общее транспортное средство (двигатель и т. д.).
Если вы попытаетесь представить любой объект в JS как набор всех поведений, доступных посредством делегирования, и мысленно приравняете это поведение к одной конкретной вещи, вы увидите, насколько подходит дифференциальное наследование. .
Но, как и наследование прототипов, дифференциальное наследование заставляет вашу ментальную модель казаться более важной, чем то, что физически происходит в языке. Он игнорирует тот факт, что объект Bis на самом деле не является дифференциально сконструированным, а вместо этого сконструирован с различными характеристиками, определенными вместе с «дырками», где ничего не определено. Именно в эти «пробелы» (пробелы или отсутствие определений) делегирование может делегироваться и они могут «заполняться» заданным поведением.
Объект по умолчанию не сводится к одному дифференциальному объекту путем копирования, как это подразумевается ментальной моделью дифференциального наследования. Таким образом, дифференциальное наследование не является естественным способом описания того, как на самом деле работает механизм JavaScript.
Вы можете выбрать терминологию дифференциального наследования и мысленную модель по своему вкусу, но нельзя отрицать, что она соответствует только ментальной акробатике в вашем уме, а не физическому поведению в движке.
«Строители»
Вернемся к предыдущему коду:
функция Foo() { // ...
}
вар а = новый Foo();
Что именно заставляет нас думать о Фу как о «классе»?
Во-первых, мы видим использование ключевого слова new, точно так же, как мы видим в классо-ориентированных языках, когда они конструируют экземпляры класса. С другой стороны, похоже, что мы на самом деле выполняем метод конструктора класса, потому что Foo() на самом деле является методом, который вызывается, когда вызывается конструктор фактического класса при создании этого класса.
Чтобы запутать семантику слова «конструктор», в произвольно помеченном объекте Foo.prototype есть еще один трюк. Рассмотрим этот код:
функция Foo() { // ...
}
Foo.prototype.constructor === Foo; // настоящий
вар а = новый Foo(); а.конструктор === Фу; // настоящий
Foo.prototypeobject по умолчанию принимает (во время объявления в первой строке фрагмента!) общедоступное, неперечисляемое (см. главу 3) свойство, называемое .constructor, и это свойство является ссылкой на функцию (в данном случае Fooin). ) объект связан. Более того, мы видим, что объект, созданный «конструктором» под названием new Foo(), похоже, имеет свойство .constructor, которое указывает на «функцию, которая его создала».
На самом деле это не так. Не существует свойства a.constructor, и хотя a.constructor на самом деле разрешается в функцию Foo, «конструктор» на самом деле не означает «созданный», как кажется. Вскоре мы объясним эту странность.
По соглашению в мире JavaScript слово «класс» пишется с заглавной буквы, поэтому наличие Fooe вместо foo доказывает, что мы хотим, чтобы это был «класс». Для тебя это очевидно, не так ли!?
Это соглашение настолько строгое, что многие JS-линтеры будут жаловаться, если вы вызываете метод newon со строчной буквы или если мы не вызываем функцию newon с прописной буквой. Уму непостижимо, что мы изо всех сил стараемся получить (фальшивое) «правильное» «направление класса» в JavaScript, что создаем правила линтера для обеспечения соблюдения капитализации, хотя для JS капитализация абсолютно ничего не значит. двигатель.
В предыдущем отрывке интересно думать о Fua как о конструкторе, поскольку мы называем его новым и замечаем, что он «конструирует» объект.
Фактически, Foo является не более «конструктором», чем любая другая функция в вашей программе. Сами функции не являются конструкторами. Однако, когда новое ключевое слово помещается перед обычным вызовом функции, функция называется «вызовом конструктора». Фактически, новый тип перехватывает любую обычную функцию и вызывает ее таким образом, что, среди прочего, конструируется объект.
Например:
function #thingSpecial() { console.log("Не обращай на меня внимания!");
}
вар а = новый NothingSpecial (); // "Не обращай на меня внимания!"
// {}
NothingSpecial — это не просто старая обычная функция, но при вызове с новой функцией она почти как побочный эффект создает объект, который мы присваиваем . Вызов был вызовом конструктора, но NothingSpecial сам по себе конструктором не является.
Другими словами, имеет смысл сказать, что любая функция в JavaScript, вызываемая с ключевым словом new перед «конструктором».
Функции не являются конструкторами, но вызовы функций являются «вызовами конструктора», только если они используются как новые.
Механика
Это единственный общий триггер неудачных обсуждений «классов» в JavaScript. Мужчины?
Нисколько. Разработчики JS постарались максимально смоделировать маршрутизацию классов:
функция Foo(имя) { this.name = name;
}
Foo.prototype.myName = function() { return this.name;
};
вар а = новый Foo("а"); вар b = новый Foo("b");
а.моеИмя(); // "а" b.myName(); // "б"
В этом фрагменте показаны два дополнительных приема «классовой ориентации» в игре:
1. this.name=name добавляет к каждому объекту свойство .name, аналогично тому, как экземпляры класса инкапсулируют значения данных (a и b соответственно; см. главу 2 об этой привязке).
2. Foo.prototype.myName = ... наверное, самый интересный метод; это добавляет свойство (функцию) к объекту Foo.prototype. Теперь a.myName() работает, но как ни странно. Как?
Очень интересно подумать, что когда a и b создаются в предыдущем фрагменте, свойства/функции Foo.prototypeobject копируются в каждый из объектов a и b. Однако этого не произойдет.
Ранее в этой главе мы объяснили ссылку и то, как она обеспечивает извлекаемые шаги как часть алгоритма по умолчанию [[Get]], если ссылка на описание не найдена непосредственно в объекте.
Таким образом, в зависимости от способа создания каждый из a и b имеет внутреннее соединение с Foo.prototype. Если myName не найден в a или b соответственно, вместо этого оно находится в Foo.prototype.




Достарыңызбен бөлісу:
1   2   3   4   5   6   7




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет