Pull to refresh

Comments 42

Лучше, чем обычно, но на мой вкус, как-то старовато. Все же сейчас мало кто реально пишет слово prototype, например
Это вы, видимо, на собеседования давно не ходили
Одно дело собеседование, где можно блеснуть знаниями, как это работает и что это за такой синтаксический сахар «class» в JS. И совсем другое дело, так делать в реальном проекте.

prototype довольно удобно до сих пор использовать в фабриках классов и миксинах.


Когда перенаследоваться по какой-то причине нельзя, а логику общую нужно вынести, можно «обогатить» прототипы родственных классов общими методами, или строить конструкторы на лету все еще бывает полезно.

Я однажды делал наследование attrHooks, вот это было классно.

function ShapeAttrHooks(){}
Shape.prototype.attrHooks = ShapeAttrHooks.prototype = {};

Rect.prototype.attrHooks = new ShapeAttrHooks();
Circle.prototype.attrHooks = new ShapeAttrHooks();

А дальше можно так:

Shape.prototype.attrHooks.foo = 3333;
// магия!
new Rect().attrHooks.foo; // 3333
миксины отличный способ запутать код понадежнее

Очень похоже на статью о Java.)
Меня в JS привлекает как раз его простота и возможность не писать лишнего.
Тем более что язык активно развивается, закрываются детские проблемы — отсутствие модульности или блочные переменные и т.п.
ООП мягко говоря спорная концепция. Где то она применима, например компоненты в React адекватно используют эту концепцию. Но в прикладном коде я не вижу смысла писать классы в 99% случаев, есть отдельно данные и функции которые их обрабатывают но не все вместе.

Компоненты в Реакте давным-давно используют хуки, а не классы. Переход с классов на хуки — это по магнитуде как был много лет назад переход с голого JS на jQuery.


Но функции-прототипы тоже давно в прошлом, конечно. Тем более с typescript и его возможностью делать вещи типа:


class Cls {
  constructor(public readonly x, public readonly y) {}
}

Хуки действительно классная концепция.
Я пока мало занимался разработкой с использованием react и не знал о них.
Уже переписал все на хуки. Кода меньше и код проще.

Давным-давно? Кажется активно год всего.
Так и без TS делать можно, только модификаторов доступа пока нет (обещают скоро подвезти)
да? а пример можно?
Где в js уже сейчас можно в параметрах конструктора сразу определить поле класса?
«7 рекомендаций по повышению надёжности JavaScript-кода» — рекомендация «Используйте Typescript». Это разные языки программирования, хоть они и реализуют один стандарт, но все же формально разные языки. Довольно странно давать такой совет.
Ещё весело, когда говорят — «Начиная с сегодня все фронтовые проекты компании пишем на TS».
Почему-то многие (почти все, кого я знаю) считают, что JS и TS — почти одно и то же. Питонистам же не предлагают вдруг пересесть на C# или Java! :)
Работал на проекте, делал модуль на JS, а спустя половину реализации, весь проект перевели на TS. К счастью VueJS достаточно умный (умнее чем тот, кто переводит проект в процессе разработки на другой язык) и я смог дописать свой модуль на JS-е, и ничего не сломалось.
потому что JS и TS — почти одно и то же

Практика показывает, что нет. Когда пишешь на TS, нужно учитывать то, как это будет выполняться на JS, потому что (внезапно) весь TS пропадает в рантайме.


TypeScript — это скорее надстройка над JS, чем отдельный язык. Можно использовать в одном проекте одновременно JS и TS файлы, и они будут уживаться друг с другом. Так можно постепенно переводить проект в JS на TS.

Есть альтернативное мнение на тему «всегда пишите тесты»
TL;DR: Надо все-таки думать головой, тесты это дорого, тесты могут цементировать архитектуру, покрытие тестами может быть «попугаями»

На «Пользуйтесь TypeScript» могу ответить «Не пользуйтесь TypeScript» :)
По моему опыту, при программировании чего-то сложнее сортировки очень большое время начинает отводиться на удовлетворение тайпскрипта, а не бизнеса.
очень большое время начинает отводиться на удовлетворение тайпскрипта, а не бизнеса.

Это с лихвой окупается за месяцы и годы поддержки и развития. Может быть для MVP он кому-то и кажется лишним, но для больших проектов с длинным циклом — must have.


Да и если освоится, и в проекте типы и так есть, то на них не так уж много времени тратиться.

Альтернативное мнение от лучших лапшеписателей?
В текущем проекте я покрыл (пока что) тестами весь слой работы с данными, при рефакторинге и расширении функционала, не так давно, они мне помогли сэкономить кучу рабочего времени и указали на места в коде, в которых буду возникать баги.
Про UI-тесты я даже писать не стану.

А ещё больше времени отнимает дебаг ошибок, вызванных опечаткой в названии атрибута глубоко вложенного объекта или передачей числа функции, которая ожидает строку.

Слушайте, а как вы без тайпскрипта понимаете, что за тип ожидается функцией в параметре? Обязательный JSDoc со спецификацией типов?
«Будем использовать TS чтобы писать хороший код, потому, что наш код состоит из настолько дерьмовых функций, что они не проверяют входящие параметры» — для меня это звучит как-то так. Хотя я вроде как бэкендщик и JS только осваиваю.

Как-как вы проверяете внутри функции входящие параметры? Вот предположим, что у меня функция ожидает в первом параметре объект rectangle, состоящий из точки левого верхнего угла и двух длин сторон:
{ upperLeft: {x:23, y:0}, height: 24, width: 60 }


}

Я же сказал, что только осваиваю, поэтому в данном случае я проверял бы в лоб каждое свойство объекта.
А как это делается в TS? Там какой-то хитрый ходи для этого есть или просто сахар который в js развернется точно в такую же проверку?

Ну я вам так скажу, сейчас в js это делается никак. Вот прямо все берут и никак это не делают, потому что проверять надо будет очень многое: что весь rectangle не null, что у reactangle есть такие-то и такие-то свойства и эти свойства имеют ожидаемые нами типы, что у объекта отсутствуют другие свойства, и прочее. Кстати, это не сильно улучшит читабельности вашего кода — пользователь функции должен будет довольно долго соображать, какой же структуры передать объект внутрь нее — будет вчитываться в ваши ифы вместо того, чтобы мельком взглянуть на указанный тип. TS для рантайма тоже не генерирует никаких проектов потому что это же будет ужас, а не код. Зато TS на этапе компиляции позволяет задать тип Reactangle и в процессе компиляции проверить, не передаёте ли вы в вашу функцию какую-нибудь фигню вместо него.

Но ведь TS просто компилируется в JS, я правильно понимаю? И там эти проверки все равно будут такими же как у меня?

Нет, в сгенерированном коде не будет никаких проверок.

Т.е. он проверит тип на этапе компиляции и просто не сгенерит код в случае ошибки?

И вот еще о чем я последнее время думаю:
В детстве мы мечтали как в будущем производительность компьютеров вырастит настолько, что мы сможем писать на языках высокого уровня почти всё. Мы наконец забудем компиляторы как страшный сон, ведь человеческое время будет дороже машинного.
Мы будем писать преимущественно на Java, JavaScript, Tcl и тому подобных языках, которые будут выполнятся сразу, без необходимости предварительной сборки или компиляции.
2020 год, и теперь у нас есть Babel, Webpack и TypeScript, для того чтобы «компилировать» наши программы в интерпретируемый (!) JS.
Как так получилось? Почему силы сообщества брошены не на то, чтобы реализовать поддержку всех этих возможностей в интерпретаторе, а на то чтобы создать прослойку сборки между редактором и интерпретатором? Что пошло не так? Где мы ошиблись?

Да, таким образом тс спасёт вас в случае, если вы опечатались в имени свойства объекта, который сами же создали. Однако если объект пришёл с API, и оказался не той структуры, которой вы ожидали, то TS тут не спасёт. Есть несколько стратегий как минимизировать эти риски.

и давно у вас Java без компиляции выполняется?
Да и js вообще-то компилируется, а не интепретируется, хотя с появлением JIT хрен пойми где там что.
js это не только v8, может есть наверно и движки чисто интерпретаторы.
Итак по пунктам

1. Фабричные функции.
В чем приимущество перед классами? Не писать new? Как делать extends? Различать по типу? И в чем проблема связываться с классом? В общем, давайте без фанатизма. Против фабричный функций ничего не имею против, но всему свое место. Не надо это лепить куда попало.

2. Прототип.
Ну ребят, ES6 не вчера же появился, и даже не позавчера. А вы продолжаете это лепить. Откройте для себя уже «class» в конце концов. Даже если вас заботит поддержка старых браузеров, то и TS и Babel давно уже могут собрать ваш код в ES5.

PS Да, классы не отменяют того, что вы должны понимать как работают прототипы под капотом и как работает наследование в JS.

7. Откройте для себя схемы и валидацию данных. Это избавит вас от ручной манипуляции. Посмотрите, к примеру, подход MongooseJS. Как там объявляются и валидируются данные.

Совет для новичков. Не стоит эти советы принимать к работе. Ознакомится — да, но не более.
С классами нужно быть очень внимательным с this
class Person{
  constructor(name){
    this.name = name;
  }
  logName(){
    console.log(this.name);
  }
}
let p = new Person('Ivan');
btn.addEventListener('click', p.logName); // проблема this не person а уже button
// нужно явно указать контекст 
btn.addEventListener('click', p.logName.bind(p));                                                          

С фабричными функциями нет проблем с this
const Person = function(name){
  let state = {
    name: name;
  };
  // Насчет extends наследование заменим композицией
  return Object.assign({ logName: () => state.name }, 
     Programmer(state), 
     Sportsmen(state)
  );
}
const sportsmenIvan = Person('Ivan');
btn.addEventListener('click', p.logName); // никаких проблем с this


Одна из причин, почему появились «arrow functions», это потеря контекста. И именно их рекомендуют использовать, как callback функции.

В вашем примере необходимо использовать:

class Person{
  constructor(name){
    this.name = name;
  }
  logName(){
    console.log(this.name);
  }
}

let p = new Person('Ivan');

btn.addEventListener('click', (e) => p.logName()); // нет магии, нет привязки.


Плюс, повышается читабельность кода.
С фабричными функциями нет проблем с this
Нет проблем с this, потому что тут не использовали this?

Я вот тоже не совсем понимаю преимуществ фабричной функции перед классом. Как по мне это два совершенно разных паттерна и применяться они должны для разных ситуаций, а иногда даже совместно.


function createSpecies(type, name, gender) {
  if (type === 'frog') {
    return new Frog(name, gender)

  } else if (type === 'human') {
    return new Human(name, gender)

  } else if (type == undefined) {
    throw new Error('Cannot create a species with an unknown type')
  }
}

const species = createSpecies('frog', 'sally', 'female');

// Проверка типов
species instanceof Frog // true
species instanceof Human // false
Название не соответствует содержанию.

И, кстати, я не понял из текста, почему так важно обрабатывать именно JSON ошибки? Они как-то особо загадочно рушат приложения? И как try/catch помог бы автору избавиться от проблемы без исправления кода «внешнего пакета»?
Видимо потому что их чаще всего игнорируют.
Я бы этот пункт переписал так: обрабатывайте все ошибки. Если что-то может выбросить ошибку — оно обязательно её выбросит, даже не сомневайтесь.

Конструкция response.data.record.id без дополнительных проверок в 99% случаев приведёт к багу рано или поздно.
Самый надежный javasctipt, это сгенерированный компилятором Elm, Purescript, Idris или Haskell.
Sign up to leave a comment.