🔖

Javascript のクラスにおける static 変数について

に公開

はじめに

株式会社カルディオインテリジェンスの幸です。
ふと Javascript のクラスにおける static な変数ってどう定義できて const も絡めるとどうなるのか気になったので調べてみました。
私自身、Javascript をずっと触ってきたわけではなく、熟練度は低いです。そういった方の一助になればと思います。

以下のサンプルは node で動くように記載していきます。

Javascript のクラス内 static 変数

Javascript のクラス内 static 変数は、class スコープの外側で定義できます。
class 内からでも参照可能です。

class1.js
class class1 {
  consoleVar() {
    console.log('consoleVar: class1.THIS_STATIC_VAR: ', class1.THIS_STATIC_VAR)
  }
}

// class スコープの外側で定義すると static 変数として定義可能
class1.THIS_STATIC_VAR = 100
module.exports = class1
main.js
const class1 = require('./class1')

console.log('class1.THIS_STATIC_VAR: ', class1.THIS_STATIC_VAR)

const class1Instance = new class1()
class1Instance.consoleVar()
出力
node main.js 
> class1.THIS_STATIC_VAR:  100
> consoleVar: class1.THIS_STATIC_VAR:  100

static 変数の書き換え

確かに static 変数を定義して参照できまた。しかし、この static 変数は「書き換え可能」になっています。なので、どなたかが勝手に書き換えてしまう可能性があります。

main.js
const class1 = require('./class1')

console.log('class1.THIS_STATIC_VAR: ', class1.THIS_STATIC_VAR)

const class1Instance = new class1()
class1Instance.consoleVar()

// class1.THIS_STATIC_VAR 更新
class1.THIS_STATIC_VAR = 1000
console.log('update: class1.THIS_STATIC_VAR: ', class1.THIS_STATIC_VAR)
class1Instance.consoleVar()
出力
node main.js 
> class1.THIS_STATIC_VAR:  100
> consoleVar: class1.THIS_STATIC_VAR:  100
> update: class1.THIS_STATIC_VAR:  1000
> consoleVar: class1.THIS_STATIC_VAR:  1000

const な static 変数

const な static 変数を定義する場合、getter を使います。
この書き方で const で static な関数も定義できますが、引数の関係やJSDocとか書く際に困るだけという印象を受けました。関数を書き換えようという人はまずいないと考えられるので、const で static な関数は定義しなくてもよいかなと思います。

class1.js
class class1 {
  // class1 の static かつ const として定義
  static get THIS_STATIC_CONST_VAR() {
    return 200
  }
}

module.exports = class1
main.js
const class1 = require('./class1')

// const かつ static な変数
console.log('class1.THIS_STATIC_CONST_VAR: ', class1.THIS_STATIC_CONST_VAR)
class1.THIS_STATIC_CONST_VAR = 2000
console.log('class1.THIS_STATIC_CONST_VAR: ', class1.THIS_STATIC_CONST_VAR)
出力
node main.js 
> class1.THIS_STATIC_CONST_VAR:  200
> class1.THIS_STATIC_CONST_VAR:  200

class ファイル内のスコープ

これまでで static 変数が定義できました。その時、「class ファイル内で定義した変数・関数のスコープはどこになるんだ?」と疑問に思ったのでついでに調べました。
javascript は厳密には class を定義せず中身は object で、「どこに何を書いたら上書きできたりするんだろうか」というのが気になったのもあります。

なお、関数については変数と同様に書くだけなので省略します。

class 内のメンバ変数

メンバ変数はおなじみ constructor で定義するものと、prototype で定義するものの2通りです。cosnt なメンバ変数にしたい機会はそれほどないと思いますが、getter を使えば const として定義は可能です。

class1.js
class class1 {
  // const なメンバ
  get CONST_MEMBER_3() {
    return 'member 3'
  }
  constructor() {
    this.MEMBER_1 = 'member 1'
  }

  consoleMember() {
    console.log('cosoleMember: ')
    console.log(this.MEMBER_1)
    console.log(this.MEMBER_2)
    console.log(this.CONST_MEMBER_3)
  }
}

// prototype に追加することでも member 変数として定義可能
class1.prototype.MEMBER_2 = 'member 2'

module.exports = class1
main.js
const class1 = require('./class1')

const class1Instance = new class1()
class1Instance.consoleMember()
class1Instance.CONST_MEMBER_3 = 100
class1Instance.consoleMember()
出力
node main.js 
> cosoleMember: 
> member 1
> member 2
> member 3
> cosoleMember: 
> member 1
> member 2
> member 3

class ファイル内のみ参照可能な変数

class スコープ外でただ const として定義した変数などはその class 外のスコープから参照できません。
これは当たり前なのであまりまとめる意味がない変数かもしれません。

class1.js

// class 外から参照不可
const CONST_VAR = 999

class class1 {
  consoleClassOnlyVar() {
    console.log(CONST_VAR)
  }
}

module.exports = class1
main.js
const class1 = require('./class1')

const class1Instance = new class1()
class1Instance.consoleClassOnlyVar()
// 以下はもちろん参照できない
console.log(class1Instance.CONST_VAR)
console.log(class1.CONST_VAR)
出力
node main.js 
> 999
> undefined
> undefined

Discussion