123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- // ООП: Прототипы и ES6 классы
- // задание 1 Store Class
- {
- class Store {
- #reducer;
- #state;
- #cbs = [];
- constructor(reducer, state) {
- this.#reducer = reducer;
- this.#state = state;
- }
- get state() {
- return this.#state;
- }
- dispatch(action) {
- this.#state = this.#reducer(this.#state, action);
- this.#cbs.forEach((cb) => cb());
- }
- subscribe(cb) {
- this.#cbs.push(cb);
- return () => (this.#cbs = this.#cbs.filter((c) => c !== cb));
- }
- }
- const reducer = (state, action) => {
- // обработка action и возврат нового состояния
- return newState;
- };
- const store = new Store(reducer, {});
- store.subscribe(() => {
- console.log('Изменено состояние:', store.state);
- });
- store.dispatch({ type: 'INCREMENT' }); // Изменено состояние: { count: 1 }
- store.dispatch({ type: 'DECREMENT' }); // Изменено состояние: { count: 0 }
- }
- // задание 2 Password Class
- {
- class Password {
- #input;
- #checkbox;
- constructor(parent, open = false) {
- this.#input = document.createElement('input');
- this.#input.type = open ? 'text' : 'password';
- this.#input.addEventListener('input', () => this.onChange(this.#input.value));
- this.#checkbox = document.createElement('input');
- this.#checkbox.type = 'checkbox';
- this.#checkbox.checked = open;
- this.#checkbox.addEventListener('change', () => this.setOpen(this.#checkbox.checked));
- parent.append(this.#input, this.#checkbox);
- }
- setValue(value) {
- this.#input.value = value;
- }
- getValue() {
- return this.#input.value;
- }
- setOpen(open) {
- this.#input.type = open ? 'text' : 'password';
- this.#checkbox.checked = open;
- this.onOpenChange(open);
- }
- getOpen() {
- return this.#checkbox.checked;
- }
- }
- }
- // задание 3 StoreThunk Class ???
- {
- class StoreThunk extends Store {
- constructor(reducer) {
- super(reducer);
- }
- dispatch(action) {
- if (typeof action === 'function') {
- return action(this.dispatch.bind(this), this.getState.bind(this));
- }
- return super.dispatch(action);
- }
- }
- }
- // или (не уверен какой из вариантов правильный)
- {
- class StoreThunk extends Store {
- constructor(reducer, state) {
- super(reducer, state);
- }
- dispatch(action) {
- if (typeof action === 'function') {
- action(this.dispatch.bind(this), this.getState.bind(this));
- } else {
- super.dispatch(action);
- }
- }
- }
- const storeThunk = new StoreThunk(reducer, {});
- storeThunk.subscribe(() => {
- console.log('State updated:', storeThunk.state);
- });
- storeThunk.dispatch({ type: 'INCREMENT' }); // State updated: { count: 1 }
- storeThunk.dispatch((dispatch, getState) => {
- setTimeout(() => {
- dispatch({ type: 'DECREMENT' });
- }, 1000);
- }); // State updated: { count: 0 } after 1 second
- }
- // задание 4 RGB Class
- {
- class RGB {
- constructor(r, g, b) {
- this.#r = r;
- this.#g = g;
- this.#b = b;
- }
- get r() {
- return this.#r;
- }
- set r(value) {
- this.#r = value;
- }
- get g() {
- return this.#g;
- }
- set g(value) {
- this.#g = value;
- }
- get b() {
- return this.#b;
- }
- set b(value) {
- this.#b = value;
- }
- get rgb() {
- return `rgb(${this.#r}, ${this.#g}, ${this.#b})`;
- }
- set rgb(value) {
- const match = value.match(
- /^(rgb)?\(?([01]?\d\d?|2[0-4]\d|25[0-5])(\W+)([01]?\d\d?|2[0-4]\d|25[0-5])\W+(([01]?\d\d?|2[0-4]\d|25[0-5])\)?)$/,
- );
- if (match) {
- this.#r = match[2];
- this.#g = match[4];
- this.#b = match[6];
- }
- }
- get hex() {
- return `#${this.#r.toString(16).padStart(2, '0')}${this.#g
- .toString(16)
- .padStart(2, '0')}${this.#b.toString(16).padStart(2, '0')}`;
- }
- set hex(value) {
- const match = value.match(/^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/);
- if (match) {
- this.#r = parseInt(match[1], 16);
- this.#g = parseInt(match[2], 16);
- this.#b = parseInt(match[3], 16);
- }
- }
- }
- }
- // задание 5 RGBA Class
- {
- class RGBA extends RGB {
- #a = 1;
- get a() {
- return this.#a;
- }
- set a(value) {
- if (value >= 0 && value <= 1) {
- this.#a = value;
- } else {
- throw new Error('Invalid value for a. Must be between 0 and 1');
- }
- }
- get hex() {
- return `#${super.hex.slice(1)}${Math.round(this.#a * 255)
- .toString(16)
- .padStart(2, '0')}`;
- }
- set hex(value) {
- if (value.length === 9) {
- super.hex = value.slice(0, 7);
- this.#a = parseInt(value.slice(7), 16) / 255;
- } else {
- super.hex = value;
- this.#a = 1;
- }
- }
- get rgba() {
- return `rgba(${this.#r}, ${this.#g}, ${this.#b}, ${this.#a})`;
- }
- set rgba(value) {
- const match = value.match(
- /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*([0-9]*\.[0-9]+|[0-9]+)\)$/,
- );
- if (match) {
- super.rgb = `rgb(${match[1]}, ${match[2]}, ${match[3]})`;
- this.#a = parseFloat(match[4]);
- }
- }
- set color(value) {
- if (value.startsWith('#')) {
- this.hex = value;
- } else if (value.startsWith('rgb')) {
- super.rgb = value;
- this.#a = 1;
- } else if (value.startsWith('rgba')) {
- this.rgba = value;
- }
- }
- }
- }
- {
- const rgba = new RGBA(0, 0, 0, 0);
- rgba.hex = '#80808080';
- console.log(rgba.a); // 0.5
- console.log(rgba.rgba); // rgba(128,128,128,0.5)
- rgba.r = 192;
- rgba.a = 0.25;
- console.log(rgba.hex); // #C0808040
- rgba.color = 'rgba(1,2,3,0.70)';
- rgba.b *= 10;
- console.log(rgba.hex); // #01021EB3
- }
|