-
Notifications
You must be signed in to change notification settings - Fork 16
Class
Синтаксический сахар на поверхности прототипной модели наследования
| class declaration | class expression |
|---|---|
Потеря контекста |
static |
| get & set | extends |
| super | ☕ Пример |
strict mode
( даже если вы не использовали директиву **_'use strict'_** )
{ }
Внутри фигурных скобок объявляются конструктор ( constructor ) и методы класса
Метод constructor создает и инициализирует экземпляра класса
Поскольку "под капотом" работает все та же прототипная модель наследования JS, создаваемые в конструкторе свойства и методы могут быть приватными и публичными ( как и в обычном конструкторе )
В обычном конструкторе контекстом вызова приватных методов будет глобальный объект window
В конструкторе класса приватные методы теряют контекст ( undefined )
class User {
constructor ( name ) {
var privateVar = prompt ( "Set privateVar value: " )
function showPrivate () {
console.log ( `Ай-яй-яй, у меня контекст вызова ${this}` )
console.log ( `Зато я вижу приватную переменную: ${privateVar}` )
}
this.name = name || "Бегемот"
this.show = function () {
showPrivate ()
}
}
}
var user = new User ( "Крокодил" )
user.show()| ⏫ |
|---|
объявление класса дожно быть раньше первого обращения к нему
Классы - это специальные функции-"обертки", в которые "заворачивают" конструктор
class Picture {
constructor ( url, width ) {
this.elem = document.createElement ( 'img' )
this.elem.src = url
this.width = width
}
}
typeof Picture // "function"
⚠️ объявленный класс невозможно удалить динамически, без перезагрузки страницы
В примере 1️⃣ идентификатор Picture уже занят, и никакие магические заклинания не помогут переопределить его содержание
⚠️ если обычный конструктор JS можно вызвать и как функцию, и как конструктор ( с ключевым словомnew), то конструктор класса вызвать без ключевого словаnewнельзя - будет сгенерировано исключение TypeError
let x = new Picture ( "http://www.radioactiva.cl/wp-content/uploads/2018/05/pikachu.jpg", 200 )
document.body.appendChild ( x.elem )| ⏫ |
|---|
let Picture = class {
constructor () {
this.canvas = document.createElement ( 'canvas' )
document.body.appendChild ( this.canvas )
this.area = this.canvas.getContext ( "2d" )
}
}
Picture.name // "Picture"let Picture = class Canvas {
constructor () {
this.canvas = document.createElement ( 'canvas' )
document.body.appendChild ( this.canvas )
this.area = this.canvas.getContext ( "2d" )
}
}
Picture.name // "Canvas"- Имя class expression является локальным для тела класса
- Оно доступно как свойство name класса
- Из экземпляра picture класса можно получить имя класса так:
picture.__proto__.constructor.name // "Canvas"let pict = new class {
constructor () {
this.canvas = document.createElement ( 'canvas' )
document.body.appendChild ( this.canvas )
this.area = this.canvas.getContext ( "2d" )
}
} ()здесь мы создаем экземпляр pict анонимного класса
pict.__proto__.constructor.name // ""const Sample = class Canvas {
constructor () {
this.canvas = document.createElement ( 'canvas' )
document.body.appendChild ( this.canvas )
this.resizeCanvas()
this.canvas.style.border = "1px solid #000000"
this.area = this.canvas.getContext ( "2d" )
}
resizeCanvas ( event ) {
this.canvas.width = window.innerWidth - 30
this.canvas.height = window.innerHeight - 20
}
drawLine ( points ) {
this.area.moveTo( points[0].x, points[0].y )
this.area.lineTo( points[1].x, points[1].y )
this.area.stroke()
}
}
let pict = new Sample ()
window.onresize = pict.resizeCanvas.bind ( pict )
pict.drawLine ( [ { x: 50, y: 50 }, { x: 250, y: 250 } ] )
pict.drawLine ( [ { x: 250, y: 250 }, { x: 100, y: 250 } ] )📌 Чтобы получить имя класса, нужно использовать его свойство name:
console.log ( Sample.name ) // "Canvas"| ⏫ |
|---|
let drawLine = pict.drawLine
drawLine ( [ { x: 50, y: 50 }, { x: 250, y: 250 } ] )будет сгенерировано исключение:
⛔️ Uncaught TypeError: Cannot read property 'area' of undefinedПередачу контекста вызова нужно сделать явным образом:
let drawLine = pict.drawLine.bind ( pict )📌 Потеря контекста ( undefined ) происходит вследствие того, что весь код внутри тела класса выполняется в strict mode, хотя явного указания 'use strict' в коде класса нет
При отсутствии явного указания на объект, вызывающий метод,
в строгом режимеthisне будет ссылкой на глобальный объектwindow
В строгом режимеthisбудетundefined
☕ 7️⃣
В этом примере контекст теряется в функции getProp(),
объявленной внутри метода addSomeInfo
( внутренняя функция не наследует контекст вызова родительской )
class User {
constructor ( name ) {
this.name = name || 'unknown'
}
addSomeInfo ( props ) {
if ( !Array.isArray ( props ) ) return
function getProp ( prop ) {
this [ prop.name ] = prop.value
}
for ( var prop of props ) {
getProp ( prop )
}
}
}Создадим экземпляр user класса User
и вызовем метод addSomeInfo
в контексте объекта user
var user = new User ( "Grig" )
user.addSomeInfo ([
{ name: "age", value: 25 },
{ name: "hobby", value: [ "football", "fishing" ] }
])⛔️ Uncaught TypeError: Cannot set property 'age' of undefined❗ Внутри функции getProp контекст вызова ( this ) оказался undefined
Теперь используем стрелочную функцию getProp, которая не теряет контекст 😉
class User {
constructor ( name ) {
this.name = name || 'unknown'
}
addSomeInfo ( props ) {
if ( !Array.isArray ( props ) ) return
var getProp = prop => this [ prop.name ] = prop.value
for ( var prop of props ) {
getProp ( prop )
}
}
}Создадим экземпляр user класса User
и вызовем метод addSomeInfo
в контексте объекта user
var user = new User ( "Grig" )
user.addSomeInfo ([
{ name: "age", value: 25 },
{ name: "hobby", value: [ "football", "fishing" ] }
])
console.log ( user )▼ User {name: "Grig", age: 25, hobby: Array(2)}
age: 25
► hobby: (2) ["football", "fishing"]
name: "Grig"
▼ __proto__:
► addSomeInfo: addSomeInfo ( props ) { if ( !Array.isArray ( props ) ) return var getProp = prop => {…}
► constructor: class User
► __proto__: Object| ⏫ |
|---|
© Irina H.Fylyppova 2018
Использование данных материалов или любой их части коммерческими школами ( курсами ) является нарушением авторских прав
| 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 |
| ⏬ |
|---|
- Блок-схема алгоритма
- Developer Tools
- Chrome DevTools
- Переменные
- Оператор typeof
- Структуры данных
- Операторы присваивания
- Логические выражения
- Условные операторы
- Инкремент
- Свойство length
- Оператор цикла for
- UTF-8
Homework
- Приведение типов
- NaN | null | Infinity
- BigInt (ES10)
- Функции
- Методы
- Методы строк
- Методы массивов
- Date ()
Самостоятельная работа
Практика (XSS)
Homework
- Циклы while и do...while
- Циклы for...of и for...in
- Параметры по умолчанию
- Объект function
Практика
Homework
- Нативные и host-объекты
- Литерал объекта
- Унаследованные свойства
- Конструктор
- Модель наследования
- Публичные и приватные свойства
- Оператор in
1
Homework
- Итерирующие методы массивов
- Тестирование производительности
- SHA
Homework
- Размеры и прокрутка элемента
- Event Loop
- async | await
- API
- REST | HATEOAS
- status codes
JSON placeholder-
JSON server
fake chat
Homework
- strict mode
- Вычисляемые имена свойств
- Краткий синтаксис методов
- Краткий литерал объекта
- Классы
Homework
- :not(:defined)
- Shadow DOM
- Custom elements
- Lifecycle hooks
- whenDefined
- <template>
- slot
1
2
3
Homework
- npm
- webpack
Упражнение 1- ES6 модули
Упражнение 2- --mode | --watch
Упражнение 3
Упражнение 4
Упражнение 5
Упражнение 6
Упражнение 7
Упражнение 8
Homework
| ⏫ |
|---|

Дополнительно
Справочная инфо
Git Bush
TCP/IP
Коды символов