【ITニュース解説】You ever defined a constant with value `1 << 2`?
2025年09月11日に「Dev.to」が公開したITニュース「You ever defined a constant with value `1 << 2`?」について初心者にもわかりやすく解説しています。
ITニュース概要
TypeScript UIフレームワークRippleの定数定義に焦点を当てた記事。`1 << 1` といった記述は、ビット左シフト演算子 (`<<`) を用いたビットフラグというテクニックだ。これは `1` を1ビット左にずらすと `2`、2ビットずらすと `4` となるように、複数の状態を効率的に管理するプログラミング手法を解説する。
ITニュース解説
この記事は、プログラミングにおける定数の定義方法、特に「ビット左シフト演算子」を用いたユニークな手法について掘り下げている。具体的には、Dominic Gannaway氏が作成したTypeScript UIフレームワークである「Ripple」のコードベースで見られる定数定義を例に挙げ、その仕組みと意図を解説するものである。システムエンジニアを目指す初心者にとって、一見すると難解に思えるこの記述が、実は非常に効率的で実践的なプログラミングテクニックであることを理解する助けとなるだろう。
まず、記事の題材となっている「Ripple」について簡単に触れておく。Rippleは、ウェブサイトなどでユーザーが目にするインターフェース、いわゆるUI(ユーザーインターフェース)を構築するためのTypeScript製フレームワークである。TypeScriptはJavaScriptに型安全性を加えた言語で、大規模な開発においてコードの品質や保守性を高める役割を果たす。Rippleのようなフレームワークは、UI開発をより効率的かつ構造的に進めるために利用される。
記事が注目しているのは、Rippleのコードベース内、「ripple/packages/ripple/…/constants.js」というファイルに記述されている定数の定義方法である。このファイルには、以下のようなコードが含まれている。
export const TEMPLATE_FRAGMENT = 1;
export const TEMPLATE_USE_IMPORT_NODE = 1 << 1;
export const IS_CONTROLLED = 1 << 2;
ここで定義されている「定数」とは、プログラムの実行中に値が変わらない固定の数値や文字列のことを指す。例えば、消費税率や円周率のように、常に一定の値を使用したい場合に定数として宣言することで、コードの可読性を高め、誤って値を変更してしまうミスを防ぐことができる。上記のコードでは、TEMPLATE_FRAGMENT、TEMPLATE_USE_IMPORT_NODE、IS_CONTROLLEDがそれぞれ定数として宣言されている。
筆者が特に興味を示したのは、1 << 1 や 1 << 2 のように、数字の間に << という記号が使われている点である。これは「ビット左シフト演算子」と呼ばれるもので、コンピューターが内部で数値を扱う際に用いる「ビット」という最小単位の情報を操作する「ビット演算子」の一種である。
ビットとは、デジタルデータを構成する最も基本的な単位であり、0か1の二つの状態しか持たない。コンピューターはすべての情報を0と1の並び、つまり2進数で表現している。例えば、私たちが普段使う10進数の「1」は2進数では「0001」と表現される。ここでいう「0001」は、4ビットの情報を表していると考えることができる。
ビット左シフト演算子 << は、その名の通り、2進数で表された数値のビットを左方向にずらす操作を行う。例えば、1 << 1 という記述は、「2進数の1(0001)を左に1ビットずらす」という意味になる。
0001 (10進数の1)
↓ 左に1ビットシフト
0010
この 0010 という2進数は、10進数に直すと「2」に相当する。つまり、1 << 1 の計算結果は「2」となる。
同様に、1 << 2 という記述は、「2進数の1(0001)を左に2ビットずらす」という意味である。
0001 (10進数の1)
↓ 左に2ビットシフト
0100
この 0100 という2進数は、10進数に直すと「4」に相当する。したがって、1 << 2 の計算結果は「4」となる。
このように、ビット左シフト演算子は、1 << n という形で使うと、2のn乗の値を効率的に計算できるという特性を持つ。1 << 0 は1、1 << 1 は2、1 << 2 は4、1 << 3 は8…という具合である。
では、なぜこのようなビット左シフトを使った定数定義がされているのか。その目的は「ビットフラグ」というプログラミングテクニックを利用することにある。ビットフラグとは、複数の異なる状態やオプションを、たった一つの数値(整数の変数)の中にビット単位で表現する方法である。
例えば、あるオブジェクトが「保存済み」「読み込み中」「エラー発生」という三つの状態を持つ場合を考える。通常であれば、これらを別々の変数で管理するか、列挙型(enum)のようなもので表現することが多い。しかし、ビットフラグを使うと、それぞれの状態に2の累乗の値を割り当て、それらの値を組み合わせることで、オブジェクトの現在の状態を一つの数値で表現できる。
TEMPLATE_FRAGMENT = 1 (2進数で 0001)
TEMPLATE_USE_IMPORT_NODE = 1 << 1 = 2 (2進数で 0010)
IS_CONTROLLED = 1 << 2 = 4 (2進数で 0100)
これらの値は、それぞれ異なるビット位置が1になっている。
TEMPLATE_FRAGMENT は一番右のビットが1。
TEMPLATE_USE_IMPORT_NODE は右から2番目のビットが1。
IS_CONTROLLED は右から3番目のビットが1。
もしあるオブジェクトが TEMPLATE_FRAGMENT と IS_CONTROLLED の両方の状態を持つ場合、これらの定数をビット単位のOR演算子(|)で組み合わせることで、一つの数値で表現できる。
1 | 4 は 0001 | 0100 で 0101 となり、10進数で「5」となる。
このようにして生成された「5」という数値を見ることで、そのオブジェクトがTEMPLATE_FRAGMENTとIS_CONTROLLEDの両方の状態を持っていることを瞬時に判断できる。特定のビットが立っているか(1であるか)どうかを確認するには、ビット単位のAND演算子(&)を使用する。例えば、5 & TEMPLATE_FRAGMENT は 0101 & 0001 で 0001 となり、これはTEMPLATE_FRAGMENTの状態が存在することを示す。
ビットフラグの利点は、複数の状態をコンパクトに表現できること、そしてビット演算が非常に高速であることである。特に、多くのオプションや状態を扱う場合にメモリ効率が良く、また条件判定も効率的に行えるため、パフォーマンスが重視されるシステムや、組み込みシステムなどリソースが限られた環境でよく利用されるテクニックである。RippleのようなUIフレームワークでも、内部でコンポーネントの状態やレンダリングのオプションなどを効率的に管理するために、このようなビットフラグが採用されていると考えられる。
この記事は、定数定義という一見単純な部分に隠された、プログラミングの奥深さと効率的な設計思想を初心者にも示している。ビット演算は普段あまり意識することのない低レベルな操作だが、コンピューターの仕組みを理解し、より高度なプログラミングスキルを身につける上で非常に重要な概念である。システムエンジニアを目指す上で、このような基礎的ながらも強力なテクニックを学ぶことは、今後の学習において大きな財産となるだろう。