JavaScriptでフラグをビットで管理する~複数の状態フラグを少ない容量で管理
概要
状態を管理する、その状態に応じて条件分岐するやり方。
フラグをビットで管理するメリットとケース
例: ランディングページで「30秒以上滞在」「スクロール深度50%到達」「フォーム入力開始」を検知し、3つとも満たしたユーザーにのみリターゲティング用のカスタムオーディエンスを送る。あるいは、ECサイトで「トップ閲覧」「カテゴリ閲覧」「詳細閲覧」を1つの数値で持ち、商品詳細まで到達したユーザーにのみ関連商品リコメンドのタグを発火させる。 個別の条件を満たしたときにフラグを立て、その組み合わせを参照して処理を分岐させる。 単純に1フラグを1変数にすると変数の数が増える。 そこで1個の変数で複数の状態をまとめて管理する方法がビットによる管理である。 なおこの考え方はJavaScriptに限らずあらゆるプログラム言語で実装が可能。 管理するフラグが多く、メモリ消費や発生するパケットを小さくする必要があるときに重要となる。
ビット
ビットは0または1の2値を表す情報の単位 それを8個つなげたもの、
11001101
は8個の0/1を表す情報を保持している。
11001101の各桁は0か1しかないので2進数として見ることができる。
これを10進数に置き換えると205ということになる。
8ビットの変数1個(0255の整数)であれば8個のビット(0/1)が収まる。
つまり0255の整数で8種類の0/1の状態を表せる。
この最小の情報の単位であるビットに対する処理がビット処理である。
フラグの定義
1<<桁で、桁は0からスタート
フラグを設定(代入)する
まず状態を表す変数を宣言
フラグDISABLEDを立てる
フラグDISABLEDとHOVERを同時に立てる(一度に代入する)
フラグのセットを作る
フラグDISABLEDを下げる
フラグを下げる場合は「&」にするのと否定の「~」を付ける
フラグDISABLEDとHOVERを同時に下げる(一度に代入する)
特定のフラグを反転させる
特定のフラグを取り出す
stateの中でDISABLEDに対応するビットの値を抜き出す(これが0でなければDISABLEDのフラグが立っていることになる)
stateの中でDISABLED、HOVERに対応する部分を抜き出す
- これが0でなければ
DISABLEDまたはHOVERのフラグが立っていることになる - これが
(STATE.DISABLED | STATE.HOVER)と等しい場合、DISABLEDとHOVERの両フラグが立っていることになる
フラグの取り出しは条件判定で使うことになる。
逆引き
| やりたいこと | 演算方法 | 演算子 | 変更したいビット | そのままにしたいビット |
|---|---|---|---|---|
| ビットをすべて反転させたい | NOT | ~ | すべて変更される | 指定不可 |
| 一部のビットを反転させたい | XOR | ^ | 反転させたいビット: 1 | 0 |
| 一部のビットをONにしたい | OR | ` | ` | ONにしたいビット: 1 |
| 一部のビットをOFFにしたい | AND | & | OFFにしたいビット: 0 | 1 |
条件判定
if (state & STATE.DISABLED) { 処理 }
if (state & (STATE.DISABLED | STATE.HOVER)) { 処理 }
!!(state & STATE.DISABLED) && 処理
ビットを使った条件
UIの状態管理の例。ボタンが無効でなく、かつホバー中の場合にのみクリック処理を実行する。
var STATE = {
DISABLED: 1 << 0,
HOVER: 1 << 1,
ACTIVE: 1 << 2
};
var btnState = parseInt(getButtonState(), 10) || 0;
// ホバー中で、かつ無効でない場合にクリック処理を許可
if ((btnState & STATE.HOVER) && !(btnState & STATE.DISABLED)) {
console.log("Click allowed");
}
// 複数フラグの同時判定(ACTIVE と HOVER の両方がある場合)
if ((btnState & (STATE.ACTIVE | STATE.HOVER)) === (STATE.ACTIVE | STATE.HOVER)) {
console.log("Active and hovering");
}
GTMのカスタムHTMLタグなど、ES5環境で動かす場合は上記のようにvarで宣言する。
