js.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //1. Store Class
  2. // Переделайте задание Store на синтаксис ES6-классов:
  3. // {
  4. //
  5. // }class Store {
  6. // #reducer;
  7. // #state;
  8. // #cbs = []
  9. //
  10. // constructor(reducer) {
  11. // this.#reducer = reducer
  12. // this.#state = (undefined, {} )
  13. // }
  14. // getState () {
  15. // return this.#state
  16. // }
  17. //
  18. // subscribe (cb) {
  19. // this.#cbs.push(cb)
  20. // return (cb) => {
  21. // this.#cbs = this.#cbs.filter(c => c !== cb)
  22. // }
  23. // }
  24. //
  25. // dispatch (action) {
  26. // const newState = this.#reducer(this.#state, action)
  27. // if (newState !== this.#state) {
  28. // this.#state = newState
  29. // for (let cb of this.#cbs)
  30. // cb()
  31. // }
  32. // }
  33. //
  34. // get state () {
  35. // return this.#state
  36. // }
  37. // }
  38. //2. Password Class
  39. // По аналогии, переделайте код задания Password в синтаксис классов ES6. Спрячьте все что можно в #приватные свойства
  40. // объектов класса. Проверьте на форме логина - ведь она использует Password
  41. // {
  42. // class Password {
  43. // #parent
  44. // #open
  45. // #inputPassword = document.createElement('input')
  46. // #btnSee = document.createElement('input')
  47. // #onChange
  48. // #onOpenChange
  49. //
  50. // onchange = () => this.setOpen(this.#btnSee.checked)
  51. //
  52. // constructor(parent, open) {
  53. // this.#parent = parent
  54. // this.#open = open
  55. //
  56. //
  57. // this.#parent.append(this.#inputPassword)
  58. // this.#btnSee.type = 'checkbox'
  59. // this.#parent.append(this.#btnSee)
  60. // this.#btnSee.onchange = this.onchange
  61. // }
  62. //
  63. // set onChange(value) {
  64. // this.#onChange = value
  65. // }
  66. //
  67. // set onOpenChange(value) {
  68. // this.#onOpenChange = value
  69. // }
  70. //
  71. // setValue(value) {
  72. // this.#inputPassword.value = value
  73. // }
  74. //
  75. // setOpen(open) {
  76. // this.#open = open
  77. // this.#inputPassword.type = this.#open ? 'text' : 'password'
  78. // }
  79. //
  80. // getValue() {
  81. // return this.#inputPassword.value
  82. // }
  83. //
  84. // getOpen() {
  85. // return this.#inputPassword.type
  86. // }
  87. // }
  88. //
  89. // const p = new Password(document.body, true)
  90. // p.onChange = data => console.log(data)
  91. // p.onOpenChange = open => console.log(open)
  92. //
  93. // p.setValue('qwerty')
  94. // console.log(p.getValue())
  95. //
  96. // p.setOpen(false)
  97. // console.log(p.getOpen())
  98. // }
  99. // StoreThunk Class
  100. // Унаследуйте класс Store в новом классе StoreThunk. Новый класс должен перекрывать метод dispatch, проверять тип
  101. // переданного экшона и если это функция, запускать её, передав у неё this.dispatch и this.getState. Данное условие
  102. // написано тут. Учтите, что в thunk передаются функции dispatch и getState без объекта до точечки, а эти методы в
  103. // классе Store являются обычными функциями, склонными к потере this. Для прибития this намертво к функции используйте
  104. // метод bind. Посмотреть можно тут и тут Проверьте на модульном проекте
  105. {
  106. class Store {
  107. #reducer;
  108. #state;
  109. #cbs = []
  110. constructor(reducer){
  111. this.#reducer = reducer
  112. this.#state = reducer(undefined, {})
  113. }
  114. getState(){
  115. return this.#state
  116. }
  117. subscribe(cb){
  118. (this.#cbs.push(cb), () => this.#cbs = this.#cbs.filter(c => c !== cb))
  119. }
  120. dispatch(action){
  121. let newState = this.#reducer (this.#state,action)
  122. if (newState !== this.#state) {
  123. this.#state = newState
  124. for ( let cb of this.#cbs) {
  125. cb ()
  126. }
  127. }
  128. }
  129. get state () {
  130. return this.#state
  131. }
  132. }
  133. class StoreThunk extends Store {
  134. dispatch(action) {
  135. //если это функция,
  136. if (typeof action === 'function') {
  137. //запускать её, передав у неё this.dispatch и this.getState; используйте метод bind
  138. return action(this.dispatch.bind(this), this.getState.bind(this))
  139. } else {
  140. super.dispatch(action)
  141. }
  142. }
  143. }
  144. }
  145. //RGB Class
  146. // Напишите класс RGB, приватными свойствами которого являются три числа #r, #g, #b. Класс должен обладать следующими
  147. // геттерами и сеттерами:
  148. class RGB {
  149. #r;
  150. #g;
  151. #b;
  152. set r (newR) {
  153. if (typeof newR !="number" || !(newR>= 0 && newR<=255)) {
  154. throw new RangeError('Неправильный формат или диапазон')
  155. } else {
  156. this.#r = newR
  157. }
  158. }
  159. set g (newG) {
  160. if (typeof newG !="number" || !(newG>= 0 && newG<=255)) {
  161. throw new RangeError('Ошибка в типе значений')
  162. } else {
  163. this.#g = newG
  164. }
  165. }
  166. set b (newB) {
  167. if (typeof newB != 'number' || !(newB>= 0 && newB<=255)) {
  168. throw new RangeError('Ошибка в типе значений')
  169. } else {
  170. this.#b = newB
  171. }
  172. }
  173. set rgb (newRgb) {
  174. let matchColors = /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/;
  175. let match = matchColors.exec(newRgb)
  176. if (match != null) {
  177. this.#r = parseInt(match[1])
  178. this.#g = parseInt(match[2])
  179. this.#b = parseInt(match[3])
  180. return
  181. } else {
  182. throw new SyntaxError('Вы пытаетесь интерпретировать синтаксически неправильный код')
  183. }
  184. }
  185. set hex (newHex){
  186. let matchColors = /^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/
  187. let match = matchColors.exec(newHex)
  188. if (match !== null) {
  189. this.#r = parseInt(match[1], 16)
  190. this.#g = parseInt(match[2], 16)
  191. this.#b = parseInt(match[3], 16)
  192. return
  193. } else {
  194. throw new SyntaxError('Вы пытаетесь интерпретировать синтаксически неправильный код')
  195. }
  196. }
  197. ////////
  198. get r (){
  199. return this.#r
  200. }
  201. get g (){
  202. return this.#g
  203. }
  204. get b (){
  205. return this.#b
  206. }
  207. get rgb (){
  208. return `rgb(${this.#r},${this.#g},${this.#b})`
  209. }
  210. get hex (){
  211. return `#${this.componentToHex(this.#r)}${this.componentToHex(this.#g)}${this.componentToHex(this.#b)}`
  212. }
  213. componentToHex(color) {
  214. let hex = color.toString(16)
  215. return hex.length == 1 ? "0" + hex : hex
  216. }
  217. }
  218. const rgb = new RGB
  219. rgb.r = 15
  220. rgb.g = 128
  221. rgb.b = 192
  222. console.log(rgb.hex) //#0F80C0
  223. console.log(rgb.rgb) //rgb(15,128,192)
  224. rgb.hex = '#203040'
  225. console.log(rgb.rgb) //rgb(32, 48, 64)
  226. rgb.rgb = 'rgb(100, 90, 50)'
  227. console.log(rgb.r, rgb.g, rgb.b) //100, 90, 50
  228. rgb.hex = 'дичь' //SyntaxError
  229. rgb.b = 1000 //RangeError