Курс молодого Frontend'ера

 JavaScript

  1. https://habr.com/ru/post/305900/
  2. https://habr.com/ru/post/460741/
  3. https://babeljs.io/docs/en/learn/
  4. https://egghead.io/lessons/javascript-const-declarations-in-es6-es2015
  5. Выразительный Javascript - https://habr.com/ru/post/253101/
Вопрос 1: Написать функцию суммирования в виде f(3)(2) // return 5

Ответ 1.1:
function f(a) {
  return function(b) {
  return a + b;
  }
}
Ответ 1.2: используется часто в React - HOC, также можно исплользовать в замыканиях, например для bind или для задачи ниже.

Вопрос 2: Исправить ошибку
function makeArmy() {  
  var shooters = [];  
  for(var i = 0; i < 10; i++) {
  var shooter = function() { 
console.log(i); 
  };
  shooters.push(shooter);
  }  
  return shooters;
}
var army = makeArmy();
army[0](); // 10 instead of 0
army[5](); // 10 instead of 5
army[9](); // 10 instead of 9

Ответ 2.1: через let
for(var i = 0; i < 10; i++) { -> for(let i = 0; i < 10; i++) }
когда выполняется блок кода for (let i=0...) {...}, для него создаётся новое лексическое окружение с соответствующей переменной i.

Ответ 2.2: через замыкание
function makeArmy() {  
    var shooters = [];  
    for(var i = 0; i < 10; i++) {
var shooter = (function(i) { 
    return function() {
console.log(i); 
}
})(i);
        shooters.push(shooter);
    }  
    return shooters;
}



TypeScript

  1. https://www.typescriptlang.org/docs/handbook/basic-types.html (там много тем нужно разворачивать до конца)
  2. https://xsltdev.ru/typescript/handbook/variable-declarations/#scoping - тоже самое но на русском
Вопрос 1: реализовать StringMap вида
mymap["a"] = "value"
mymap["a"] = 1 //error type not string

Ответ 1
type StringMap = {
  [key: string]: string;
};

Вопрос 2: key каким может быть в решение выше? 
Ответ 2: int, string, в отдельном классе Map ключи уже могут быть объектами

Вопрос 3: для чего нужны генерики? пример генериков?
Ответ 3: для типизации объектов в структуре, например array<T>

Вопрос 4: Переделать StringMap из решения 1 в generic
Ответ 4:
type Map<T> = {
  [x: string]: T;
};

Вопрос 5: Что вернет код?
function checkGrants(user: User) {
  if (user instanceOf AdminUser) {
return true;
  }
  return false;
}
class AdminUser extends User {
  name: string
}
const adminUser2: AdminUser = {name: "admin"} //no error
checkGrants(new AdminUser("admin")) //?
checkGrants(adminUser2) //?

Ответ 5: true, false

Вопрос 6: Как его исправить?

Ответ 6.1: Утиная типизация
class AdminUser extends User {
  isAdmin: boolean = true
}
const adminUser2: AdminUser = {name: "admin", isAdmin: true}

Ответ 6.2: Часто такое может встретитться при преобразовниее респонса из строки в объект


RxJs

Вопрос 1: Как лучше переписать код?
const click$ = Rx.Observable.fromEvent(document, 'click');
const x$ = new Rx.Subject();
click$.subscribe((ev) => {
  x$.next(ev.clientX);
});
x$.subscribe((clientX) => {
  console.log(clientX);
}

Ответ 1:
const click$ = Rx.Observable.fromEvent(document, 'click');
const x$ = click$.map(ev => ev.clientX);
x$.subscribe((clientX) => {
console.log(clientX);
}

Вопрос 2: В чем отличие mergeMap vs switchMap?

Ответ 2.1: В основном лучше всегда пользоваться switchMap, т.к. mergeMap создает новый обсервабл и не закрывает старый

Ответ 2.2: С mergeMap несколько кликов создают несколько последовательностей а не переключаются на одну новую как хотелось бы.
//https://jsbin.com/faroziyixo/edit?html,console,output
<script
 src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.4/rxjs.umd.js">
</script>
<script>
const click$ = rxjs.fromEvent(document, 'click');
const tickWhenClick$ = click$.pipe(
   rxjs.operators.mergeMap(ev => rxjs.interval(1000)) //correct switchMap
); 
tickWhenClick$.subscribe((x) => { console.log(x); });
</script>

Вопрос 3: Как лучше написать код?
a$.subscribe(aData => {
   api.get$(aData).subscribe(bData=> {
console.log(bData)
   })
});

Ответ 3:
a$.switchMap(aData => {
  return api.get$(aData)
}).subscribe(bData=> {
  console.log(bData)
});

Вопрос 4: можно ли использовать tap чтобы передать данные в какой-нить сервис?
a$
  .tap((value) => {someServiceB.set(value)})
  .subscribe((value) => {someServiceA.set(value)})

Ответ 4: Нет - приемник всегда один - сайдэффекты должны быть только в subscribe иначе потом все запутается
a$
  .tap((value) => {console.log(value)})
  .subscribe((value) => {
       someServiceA.set(value); 
       someServiceB.set(value);
   })

Angular

Вопрос 1: как сделать <div *ngIf *ngFor /> ?

Ответ 1.1:
<ng-template [ngIf]="">
  <div *ngFor=""></div>
</ng-template>

Ответ 1.2:

Вопрос 2: Как создать динамическую компоненту?
Ответ 2.1
Ответ 2.2
@Component({
  selector: 'app-root',
  template: '<div #placeholder/></div>'
})
class HostComponent {  
  @ViewChild('placeholder') placeholder: ElementRef;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
  
  loadComponent() {
    const componentFactory = this.componentFactoryResolver
          .resolveComponentFactory(MyDynamicComponent);
    const viewContainerRef = this.placeholder.viewContainerRef;
    const componentRef: ComponentRef<MyDynamicComponent> =
          viewContainerRef
             .createComponent<MyDynamicComponent>(componentFactory);
    componentRef.instance.someInputData = "some data";
  }
}

Вопрос 3: Что здесь плохого?
private print() {
   let a, b;
   this.translate.get("transUnitA").subscribe(v => a = v);
   this.translate.get("transUnitB").subscribe(v => b = v);
   this.innerHtml = a + "_" + b;
}

Ответ 3.1: racecondition
private print() {
   let a, b;
   this.translate
      .get(["transUnitA", "transUnitB"]).subscribe([a,b] => {
           this.innerHtml = a + "_" + b;
      });
}

Ответ 3.2: memory leak
private print() {
   let a, b;
   this.subscription = this.translate
      .get(["transUnitA", "transUnitB"]).subscribe([a,b] => {
           this.innerHtml = a + "_" + b;
      });
}
private onNgDestroy() {
    this.subscription.unsubscribe();
}

Вопрос 4: Что здесь может быть плохого?
@Input() model;
private change(name) {
   this.model.name = name;
}

Ответ 4: не соблюдение принципа неизменяемости данных
private change(name) {
   //new object will work with shallow equals
   this.model = {...model, name}; 
}

Комментарии

Популярные сообщения из этого блога

Нейронная сеть для обхода препятствий

Time Zones

Звания IT-работников