//1. Store Class // Переделайте задание Store на синтаксис ES6-классов: // { // // }class Store { // #reducer; // #state; // #cbs = [] // // constructor(reducer) { // this.#reducer = reducer // this.#state = (undefined, {} ) // } // getState () { // return this.#state // } // // subscribe (cb) { // this.#cbs.push(cb) // return (cb) => { // this.#cbs = this.#cbs.filter(c => c !== cb) // } // } // // dispatch (action) { // const newState = this.#reducer(this.#state, action) // if (newState !== this.#state) { // this.#state = newState // for (let cb of this.#cbs) // cb() // } // } // // get state () { // return this.#state // } // } //2. Password Class // По аналогии, переделайте код задания Password в синтаксис классов ES6. Спрячьте все что можно в #приватные свойства // объектов класса. Проверьте на форме логина - ведь она использует Password // { // class Password { // #parent // #open // #inputPassword = document.createElement('input') // #btnSee = document.createElement('input') // #onChange // #onOpenChange // // onchange = () => this.setOpen(this.#btnSee.checked) // // constructor(parent, open) { // this.#parent = parent // this.#open = open // // // this.#parent.append(this.#inputPassword) // this.#btnSee.type = 'checkbox' // this.#parent.append(this.#btnSee) // this.#btnSee.onchange = this.onchange // } // // set onChange(value) { // this.#onChange = value // } // // set onOpenChange(value) { // this.#onOpenChange = value // } // // setValue(value) { // this.#inputPassword.value = value // } // // setOpen(open) { // this.#open = open // this.#inputPassword.type = this.#open ? 'text' : 'password' // } // // getValue() { // return this.#inputPassword.value // } // // getOpen() { // return this.#inputPassword.type // } // } // // const p = new Password(document.body, true) // p.onChange = data => console.log(data) // p.onOpenChange = open => console.log(open) // // p.setValue('qwerty') // console.log(p.getValue()) // // p.setOpen(false) // console.log(p.getOpen()) // } // StoreThunk Class // Унаследуйте класс Store в новом классе StoreThunk. Новый класс должен перекрывать метод dispatch, проверять тип // переданного экшона и если это функция, запускать её, передав у неё this.dispatch и this.getState. Данное условие // написано тут. Учтите, что в thunk передаются функции dispatch и getState без объекта до точечки, а эти методы в // классе Store являются обычными функциями, склонными к потере this. Для прибития this намертво к функции используйте // метод bind. Посмотреть можно тут и тут Проверьте на модульном проекте { class Store { #reducer; #state; #cbs = [] constructor(reducer){ this.#reducer = reducer this.#state = reducer(undefined, {}) } getState(){ return this.#state } subscribe(cb){ (this.#cbs.push(cb), () => this.#cbs = this.#cbs.filter(c => c !== cb)) } dispatch(action){ let newState = this.#reducer (this.#state,action) if (newState !== this.#state) { this.#state = newState for ( let cb of this.#cbs) { cb () } } } get state () { return this.#state } } class StoreThunk extends Store { dispatch(action) { //если это функция, if (typeof action === 'function') { //запускать её, передав у неё this.dispatch и this.getState; используйте метод bind return action(this.dispatch.bind(this), this.getState.bind(this)) } else { super.dispatch(action) } } } } //RGB Class // Напишите класс RGB, приватными свойствами которого являются три числа #r, #g, #b. Класс должен обладать следующими // геттерами и сеттерами: class RGB { #r; #g; #b; set r (newR) { if (typeof newR !="number" || !(newR>= 0 && newR<=255)) { throw new RangeError('Неправильный формат или диапазон') } else { this.#r = newR } } set g (newG) { if (typeof newG !="number" || !(newG>= 0 && newG<=255)) { throw new RangeError('Ошибка в типе значений') } else { this.#g = newG } } set b (newB) { if (typeof newB != 'number' || !(newB>= 0 && newB<=255)) { throw new RangeError('Ошибка в типе значений') } else { this.#b = newB } } set rgb (newRgb) { let matchColors = /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/; let match = matchColors.exec(newRgb) if (match != null) { this.#r = parseInt(match[1]) this.#g = parseInt(match[2]) this.#b = parseInt(match[3]) return } else { throw new SyntaxError('Вы пытаетесь интерпретировать синтаксически неправильный код') } } set hex (newHex){ let matchColors = /^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/ let match = matchColors.exec(newHex) if (match !== null) { this.#r = parseInt(match[1], 16) this.#g = parseInt(match[2], 16) this.#b = parseInt(match[3], 16) return } else { throw new SyntaxError('Вы пытаетесь интерпретировать синтаксически неправильный код') } } //////// get r (){ return this.#r } get g (){ return this.#g } get b (){ return this.#b } get rgb (){ return `rgb(${this.#r},${this.#g},${this.#b})` } get hex (){ return `#${this.componentToHex(this.#r)}${this.componentToHex(this.#g)}${this.componentToHex(this.#b)}` } componentToHex(color) { let hex = color.toString(16) return hex.length == 1 ? "0" + hex : hex } } const rgb = new RGB rgb.r = 15 rgb.g = 128 rgb.b = 192 console.log(rgb.hex) //#0F80C0 console.log(rgb.rgb) //rgb(15,128,192) rgb.hex = '#203040' console.log(rgb.rgb) //rgb(32, 48, 64) rgb.rgb = 'rgb(100, 90, 50)' console.log(rgb.r, rgb.g, rgb.b) //100, 90, 50 rgb.hex = 'дичь' //SyntaxError rgb.b = 1000 //RangeError