◆ this が面倒
  ◆ 関数にメソッドを渡すときは特に
◆ クラスを使うメリットがない
  ◆ bind したりプロパティに代入するなら prototype だけに関数を置いて効率化できない
  ◆ プロパティ代入だと継承して親メソッド呼び出せないし そもそも継承を使わない
◆ 関数のみで良いと思う

React を書いてると this を一切見なくて済みますし this が出てこなければ余計なところに気を使わなくていいですし この点ではすごく快適です
その分 他のツールを使っているときに クラスが出てきて this が入ってくるとすごくイヤな気分になります

クラス構文でも prototype でも クラス風にすると this が入ってきて関数に渡すときに不便です

class A {
value = 10

method() {
console.log("value is", this.value)
}
}

const a = new A()
a.method()
// value is 10

単純に関数に渡した場合に this のコンテキストが変わるので

setTimeout(a.method, 0)
// value is undefined

これを避けるためには

setTimeout(a.method.bind(a), 0)

setTimeout(() => a.method(), 0)

のように bind するとか コンテキストを維持して呼び出す関数を作って渡すとか
一手間必要です

クラス構文でメソッド定義ではなく プロパティ代入とすれば回避はできます

class B {
value = 10
method = () => {
console.log("value is", this.value)
}
}

const b = new B()
b.method()
// value is 10

setTimeout(b.method, 0)
// value is 10

全部これでいいやと思うほどですが これってクラスのメリットがなくなってるんですよね
prototype にメソッドが定義されずすべてのオブジェクトのプロパティに関数を代入しています
メソッドなら関数の実体はひとつにしてそれぞれのオブジェクトが関数を持たなくて良いメリットがあるのですが それがなくなります

しかしメソッド定義にしても関数を渡すときに bind したりその場で関数を作るなら結局関数をオブジェクトごとに作ってるのと変わりません
メソッドを関数に渡す前提だと メソッド定義か代入かに関わらずこのクラスのメリットは活かせなさそうです
これまではインスタンスを大量に作るなら効率的にクラスの方がいいかなと使い分ける基準にしていたこともありましたが この点ではクラスにする意味がなくなりました

他のクラスのメリットには継承ができることがあります
これは prototype に関数が入ってる前提なので プロパティ代入になると動かなくなります

class C extends B {
method = () => {
super.method()
console.log("C.method")
}
}

const c = new C()
c.method()
// TypeError: (intermediate value).method is not a function

B.prototype.method はないので super.method() 呼び出しに失敗します
prototype にも関数があればいいので こういうことをすれば一応動かせます

class D {
value = 10
method() {
console.log("value is", this.value)
}
method = this.method.bind(this)
}

class E extends D {
method() {
super.method()
console.log("E.method")
}
method = this.method.bind(this)
}

new D().method()
// value is 10

new E().method()
// value is 10
// E.method

動くとはいえ 見た目と二度手間感からこれは避けたいところです

それに そもそも継承っているのでしょうか?
普段から継承が必要になること自体がほぼないです
CustomElements 以外で extends を書いた記憶なんてほぼないです

必要になっても 継承以外の方法も取れます

class F {
value = 10
method = () => {
console.log("value is", this.value)
}
}

class G {
sup = new F()
method = () => {
this.sup.method()
console.log("G.method")
}
}

new G().method()
// value is 10
// G.method

これでいいと思うんです
内部で親クラスのインスタンスを持っていると メモリ使用量や関数を 1 つ多く呼び出す分パフォーマンスは落ちますが 今の時代に気にするほどのものではないはずです
React でも継承ではなく合成を使うべき みたいなこと言ってますし

これら以外にクラスを使うメリットって特に思いつかないですし それらが活かせないなら関数で十分だと思います

const f1 = () => {
const value = 10
const method = () => {
console.log("value is", value)
}

return { method }
}

シンプルな関数なので クラスよりも読みやすいですし this がいらないです
value が外から見れないので 公開したくないものを簡単に隠せます

公開したいなら返すオブジェクトに含めて アクセスはそのオブジェクトを経由すればいいです

const f2 = () => {
const method = () => {
console.log("value is", exposed.value)
}

const exposed = {
method,
value: 10,
}
return exposed
}

というわけで 最近はクラスはほとんど書いてないです

特に困ってませんが instanceof が使えないなと思ったことはあります
ただそれも返すオブジェクトに $type みたいなプロパティを用意して型情報を入れておけば済みます
扱いづらい instanceof 演算子を使わず単なる === 比較でできます
また 継承はしてないけどその型だと扱わせたいときがたまにあります
そういうときにこの方法だとプロパティに入ってる型名の書き換えで対応できます

プロパティに含めたくないなら 特別に扱えるように Symbol をキーにしたり WeakSet にインスタンスオブジェクトを入れることでも対応できます

const f3 = () => {
const instance = {}
f3.instances.add(instance)
return instance
}
f3.instances = new WeakSet()

const obj = f3()
f3.instances.has(obj)
// true

クラスを積極的に使ってる人って TypeScript で書いてる人だったりしますし JavaScript だと関数だけでも良さそうです