1. 正の数だけを足す
  2. 加算が 1 件も無い
  3. マイナスと 0 は弾く
  4. 初期値がマイナスなら 0 から始める
コース一覧
モダンJavaScript:データ処理とコード設計
private フィールドとアクセサ

モダンJavaScript:データ処理とコード設計

配列の map・filter・reduce・sort、クロージャと高階関数、オブジェクトとクラス、エラー設計、正規表現を学ぶ全 36 レッスン(665 分)のコースです。ローカルの作品データを題材に、表示とデータを分け、絞り込み・並び替え・入力検証までを組み立てます。Promise、fetch、API 通信、モジュールは次のコースで扱います。

1
土台をそろえる
01. このコースで育てるもの15分
02. strict mode が先に教えてくれる間違い15分
03. 表示とデータを切り分ける20分
04. 第1章まとめクイズ10分
2
配列をパイプラインで扱う
01. map で形を変える20分
02. filter と find で絞り込む20分
03. reduce でひとつにまとめる20分
04. sort と比較関数20分
05. 分類してまとめる groupBy20分
06. つなげて組み立てる20分
07. つくる 作品一覧の絞り込みと並び替え30分
08. 第2章まとめクイズ10分
3
関数を道具にする
01. クロージャで状態を閉じ込める20分
02. 設定を覚えた関数をつくる20分
03. 関数を返す関数20分
04. 副作用のない関数20分
05. 第3章まとめクイズ10分
4
オブジェクトを扱いきる
01. 分割代入で必要な値だけ取り出す20分
02. スプレッドとレストで組み替える20分
03. keys と values と entries20分
04. ビット演算でフラグをまとめる20分
05. 第4章まとめクイズ10分
5
クラスで型をつくる
01. クラスとインスタンス20分
02. private フィールドとアクセサ20分
03. 継承と super20分
04. 多態と static20分
05. つくる 作品コレクションをクラスにする30分
06. 第5章まとめクイズ10分
6
エラーを設計する
01. try catch finally20分
02. 自分でエラーを投げる20分
03. 失敗を画面に出す25分
04. 第6章まとめクイズ10分
7
正規表現
01. 正規表現のきほん20分
02. 入力を検証する20分
03. 置換とキャプチャ20分
04. 第7章まとめクイズ10分

private フィールドとアクセサ

# は外から触れない
解説

このレッスンで分かること

  • # を先頭に付けたフィールドは、クラスの外から一切触れません
  • get と set は、プロパティに見えるのに中で検査が走る窓口です

直接代入できる値は、いつか壊れる

前のレッスンの Skill は、学習時間をただのプロパティで持っていました。

JavaScript

const skill = new Skill("HTML", 12); skill.hours = -50; console.log(skill.hours); // -50

学習時間が負になることは現実には起こりませんが、代入は通ってしまいます。おかしな値が入った瞬間には何も起きず、合計や並び替えの場面で初めて表示が崩れます。原因から遠い場所でバグが出るので、探すのに時間がかかります。

「気をつけて代入する」では防げません。半年後の自分も他の人も、書き換えられると知っていれば書き換えます。書き換えられない形にするのが唯一の対策です。

# を付けると外から触れなくなる

フィールド名の先頭に # を付けると、そのクラスの本体の中でしか読み書きできなくなります。

JavaScript

class Skill { #hours = 0; constructor(name, hours) { this.name = name; this.#hours = hours; } get hours() { return this.#hours; } } const skill = new Skill("HTML", 12); console.log(skill.hours); // 12 skill.#hours = -50; // SyntaxError

クラスの本体の外に #hours と書いた時点で構文エラーです。実行時に弾かれるのではなく、そもそも読み込めません。使う前に #hours = 0; とクラスの直下で宣言しておく必要があります。

書きかた外から読めるか外から書けるか破られたときに気付けるか
this.hours読める書ける気付けない
this._hours読める書ける気付けない
this.#hours読めない書けない構文エラーで止まる

_ を付ける昔ながらの書きかたはただの名前なので、外から skill._hours = -50 と書けば通ります。# は言語の機能なので、約束ではなく仕組みで守られます。

窓口を get と set にする

読むだけなら get、書き込みも許すなら set を足します。

JavaScript

class Skill { #hours = 0; set hours(value) { this.#hours = value > 0 ? value : 0; } get hours() { return this.#hours; } get summary() { return `${this.name} ${this.#hours} 時間`; } }

呼ぶ側は skill.hours と書くだけで、かっこは付けません。見た目はただのプロパティなのに、読むときは get、書くときは set の中身が動きます。get だけ書いて set を書かなければ読み取り専用になり、代入は黙って無視されます。

summary のように他のフィールドから毎回作れる値は、フィールドとして持ちません。持つと、時間を更新したときに古い文字が残ります。

ただし set で黙って丸めると、呼ぶ側は「入れた値が受け取られたのか、直されたのか」を知る手立てがありません。何度も呼ぶ操作は、成否を返すメソッドにしておきます。

JavaScript

record(minutes) { if (this.#hours >= 100) { return false; // 上限なので受け付けない } this.#hours += minutes; return true; }

true か false が返るので、呼ぶ側は弾かれた回数を数えたり、画面に注意書きを出したりできます。中の値は守ったまま、外には十分な情報が渡ります。

解説

全部を # にすれば安全、ではありません。決まった範囲を外れてはいけない値だけを # にして検査を通し、作ったあと変わらない値は普通のプロパティのままでかまいません。

よくある間違い

  • # フィールドを宣言せずに使う — constructor の中でいきなり this.#hours = 0 と書いても、クラスの直下に宣言が無ければ構文エラーです
  • set の中で同じ名前に代入する — set hours(value) の中で this.hours = value と書くと set hours が呼ばれ続け、スタックがあふれます。代入先は #hours です
  • get にかっこを付けて呼ぶ — skill.hours() は、返ってきた数値を関数として呼ぼうとして TypeError になります

要件

  1. class Work は #views を private フィールドとして持つ。constructor は title と initialViews を受け取り、initialViews が 0 以下のときは #views を 0 にする
  2. get views() で #views を返す。get label() で タイトル N 回表示 の形の文字列を返す
  3. addViews(count) は count が 0 以下なら何もせず false を返し、それ以外は #views に足して true を返す
  4. function trackWorkViews(title, initialViews, counts) を定義する。counts の各要素を addViews に渡し、{ title, views, label, rejected } を返す。rejected は false が返った回数

入出力例

trackWorkViews("プロフィールサイト", 120, [10,5]) → {"label":"プロフィールサイト 135 回表示","rejected":0,"title":"プロフィールサイト","views":135} trackWorkViews("自己紹介カード", 0, []) → {"label":"自己紹介カード 0 回表示","rejected":0,"title":"自己紹介カード","views":0} trackWorkViews("スキル一覧の表", 32, [-5,0,8]) → {"label":"スキル一覧の表 40 回表示","rejected":2,"title":"スキル一覧の表","views":40} trackWorkViews("学習ログ", -10, [3]) → {"label":"学習ログ 3 回表示","rejected":0,"title":"学習ログ","views":3}

ヒント

#views はクラスの直下で #views = 0; のように宣言してから使います。宣言せずに constructor で代入すると構文エラーです

get label() はかっこなしで work.label と読みます。戻り値の label には work.label をそのまま入れます

set views(value) の中で this.views = value と書くと自分自身を呼び続けて止まらなくなります。代入先は #views です

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/03/27·更新 2026/08/26

関連レッスン

  • 継承と super

    extends で Work を受け継いだ FeaturedWork を作ります。super で親の constructor と親のメソッドを呼び、差分だけを書きます。

  • 多態と static

    同じ名前のメソッドを種類ごとに用意すると、呼ぶ側から if が消えます。static のフィールドで作った件数を数え、static のメソッドをインスタンスを作る窓口にします。

  • つくる 作品コレクションをクラスにする

    第5章で学んだ class と # と extends と static を全部使い、作品 1 件の Work と、その集まりの WorkCollection にまとめます。

  • 第5章まとめクイズ

    class と constructor、# の private フィールド、extends と super、static の 4 つを、コードを読んで結果を答える形で確かめます。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • フィールドクラスが持つデータ
  • クラスデータと振る舞いを束ねる単位
  • プロパティメソッドを属性のようにアクセスできるようにするデコレータ。
  • メソッドクラスに属する関数
  • スタック後入れ先出し(LIFO)のデータ構造
  • 関数処理に名前を付けて再利用できる単位
main.js
学習モード
エディタを読み込んでいます

メモ

private フィールドとアクセサ

⌘S で保存