ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

書籍:JavaScript本格入門


JavaScript本格入門

タイトルJavaScript本格入門
モダンスタイルによる基礎から現場での応用まで
“とりあえず動く”で立ち止まらず、古びない本質を習得するために。
著者山田祥寛/著
改訂3版
出版者東京 技術評論社
出版年2023.2
形態事項623p 23cm
ISBN978-4-297-13288-0
価格(本体価格 \3200)
NDC10(NDC9)007.645 (547.4833)
予約日2026.08.26(水)


書籍 公開:2026.08.27(木) 08:23

書籍:これからのJavaScriptの教科書


これからのJavaScriptの教科書

タイトルこれからのJavaScriptの教科書
モダンJavaScriptを基礎から実用レベルまで
著者狩野祐東/著
出版者東京 SBクリエイティブ
出版年2024.6
形態事項16,591p 24cm
ISBN978-4-8156-1802-5
価格(本体価格 \3200)
NDC10(NDC9)007.64 (007.64)
予約日2026.08.26(水)


書籍 公開:2026.08.27(木) 08:22

JavaScript #9:電卓に1文字消すボタンを追加する

公開:2026.05.10(日) 12:42

電卓に1文字消すボタンを追加する

打ち間違えた際に1文字削除するための1文字削除(バックスペース)キーを追加してみる。
この機能を実装するには、JavaScriptの文字列操作(Slice)を使う。
VB.NETでは String.Substring や、1文字削る String.Remove に相当。

1. index.html修正
"C"(クリア)ボタンの隣あたりに、バックスペースボタンを追加する。
  <button>C</button>
+ <button id="backspace">⌫</button>
  <button>=</button>

2. calculatorLogic.js修正 1文字削除する deleteLastChar メソッドを追加する。
export function deleteLastChar(currentValue) {
    // 1文字削った結果を返す
    return currentValue.slice(0, -1);
}

3. main.js修正
deleteLastCharメソッドをインポート、button.id=backspace クリック時にdeleteLastCharメソッドを呼び出すように修正する。

  import './style.css'
- import { calculate, clearDisplay } from './calculatorLogic.js'
+ import { calculate, clearDisplay, deleteLastChar } from './calculatorLogic.js'
 :
  buttons.forEach(button => {
      button.addEventListener('click', () => {
          const value = button.textContent;
  
+         if (button.id === 'backspace') {
+            display.value = deleteLastChar(display.value);
+             return;
+         }
 ;

参考(全体ソース)

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Vite 電卓</title>
  </head>
  <body>
    <div id="app">
      <!-- ここに電卓のHTMLを貼り付けます -->
      <div id="calculator">
          <input type="text" id="display" readonly>
          <div class="buttons">
              <button>7</button><button>8</button><button>9</button><button>/</button>
              <button>4</button><button>5</button><button>6</button><button>*</button>
              <button>1</button><button>2</button><button>3</button><button>-</button>
              <button>0</button>
              <button>C</button>
              <button id="backspace">⌫</button>
              <button>=</button>
              <button>+</button>
          </div>
      </div>
      <div id="history-container">
        <h3>計算機能</h3>
        <ul id="history-list"></ul>
        <button id="clear-history">履歴をクリア</button>
      </div>
    </div>
    <script type="module" src="./src/main.js"></script>
  </body>
</html>

calculatorLogic.js
// calculatorLogic.js の先頭に必要です
import { evaluate } from 'mathjs';

export function calculate(expression) {
    try {
        return evaluate(expression); // window.math ではなく直接 evaluate を使う
    } catch (error) {
        console.error("計算エラー:", error); 
        return 'Error';
    }
}

export function clearDisplay() {
    return '';
}

export function deleteLastChar(currentValue) {
    // 1文字削った結果を返す
    return currentValue.slice(0, -1);
}

main.js
import './style.css'
import { calculate, clearDisplay, deleteLastChar } from './calculatorLogic.js'

const display = document.getElementById('display');
const buttons = document.querySelectorAll('#calculator .buttons button');
// 履歴を表示するulノード
const historyList = document.getElementById('history-list');
// 履歴をクリアするボタン
const clearHistoryBtn = document.getElementById('clear-history');

// 履歴を格納するための historyData配列 を追加
let historyData = [];

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.textContent;
 
        if (button.id === 'backspace') {
            display.value = deleteLastChar(display.value);
            return;
        }

        if (value === 'C') {
            display.value = clearDisplay();
        } else if (value === '=') {
            // "="の処理で historyData配列 へ値の追加と liノードの追加
            const expression = display.value;
            const result = calculate(display.value);

            if (result !== 'Error') {
                historyData.unshift(`${expression} = ${result}`);
                renderHistory();
                saveHistory();
            }
            display.value = result;
        } else {
            display.value += value;
        }
    });
});

// 履歴クリア処理
function renderHistory() {
    historyList.innerHTML = '';

    historyData.forEach(item => {
        const li = document.createElement('li');
        li.textContent = item;
        historyList.appendChild(li);
    });
}

//  履歴をクリアボタンにイベント登録
clearHistoryBtn.addEventListener('click', () => {
    historyData = [];
    renderHistory();
});

// ローカルストレージへの保存
function saveHistory() {
    // 配列をJSON文字列に変換して保存
    localStorage.setItem('calculator-history', JSON.stringify(historyData));
}

// ローカルストレージからの復元
function loadHistory() {
    const savedData = localStorage.getItem('calculator-history');
    if (savedData) {
        // JSON文字列を配列に戻す
        historyData = JSON.parse(savedData);
        renderHistory();
    }
}

// 起動時に実行
loadHistory();


"JavaScript 学習"

JavaScript #8:電卓の履歴をローカルストレージに保存する

公開:」2026.05.09(土) 18:38

電卓の履歴をローカルストレージに保存する

1. LocalStorage(ローカルストレージ)
ブラウザにデータを保存するための仕組み
VB.NETでいうところの「設定ファイル(App.config / Settings.settings)」や「簡易的なXML保存」に近い感覚
サーバーやデータベースを用意しなくても、ユーザーのブラウザ内にデータが残り続ける

2. LocalStorageの特徴
・永続性:ブラウザを閉じても、PCを再起動してもデータは消えない
・容量:約5MBまで
・形式:文字列(String)のみ

3. main.js修正
◆ "="ボタンクリックの差異、履歴(historyData配列)を文字列へ変換しLocalStorageに"calculate-history"の名前で保存
 :
} else if (value === '=') {
 :
    if (result !== 'Error') {
        historyData.unshift(`${expression} = ${result}`);
        renderHistory();
        saveHistory();
 :
// ローカルストレージへの保存
function saveHistory() {
    // 配列をJSON文字列に変換して保存
    localStorage.setItem('calculator-history', JSON.stringify(historyData));
}

◆ アプリ起動時にLocalStorageより"calculate-history"のデータを取り出し配列に変換、historyData配列に保存
また、renderHistoryメソッドを呼び出し画面に履歴を描画する
// ローカルストレージからの復元
function loadHistory() {
    const savedData = localStorage.getItem('calculator-history');
    if (savedData) {
        // JSON文字列を配列に戻す
        historyData = JSON.parse(savedData);
        renderHistory();
    }
}

// 起動時に実行
loadHistory();

これで ブラウザでF5キーでリロード しても履歴が消えなくなる

参考(全体ソース)

main.js
import './style.css'
import { calculate, clearDisplay } from './calculatorLogic.js'
 
const display = document.getElementById('display');
const buttons = document.querySelectorAll('#calculator .buttons button');
// 履歴を表示するulノード
const historyList = document.getElementById('history-list');
// 履歴をクリアするボタン
const clearHistoryBtn = document.getElementById('clear-history');

// 履歴を格納するための historyData配列 を追加
let historyData = [];

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.textContent;
 
        if (value === 'C') {
            display.value = clearDisplay();
        } else if (value === '=') {
            // "="の処理で historyData配列 へ値の追加と liノードの追加
            const expression = display.value;
            const result = calculate(display.value);

            if (result !== 'Error') {
                historyData.unshift(`${expression} = ${result}`);
                renderHistory();
                saveHistory();
            }
            display.value = result;
        } else {
            display.value += value;
        }
    });
});

// 履歴クリア処理
function renderHistory() {
    historyList.innerHTML = '';

    historyData.forEach(item => {
        const li = document.createElement('li');
        li.textContent = item;
        historyList.appendChild(li);
    });
}

//  履歴をクリアボタンにイベント登録
clearHistoryBtn.addEventListener('click', () => {
    historyData = [];
    renderHistory();
});

// ローカルストレージへの保存
function saveHistory() {
    // 配列をJSON文字列に変換して保存
    localStorage.setItem('calculator-history', JSON.stringify(historyData));
}

// ローカルストレージからの復元
function loadHistory() {
    const savedData = localStorage.getItem('calculator-history');
    if (savedData) {
        // JSON文字列を配列に戻す
        historyData = JSON.parse(savedData);
        renderHistory();
    }
}

// 起動時に実行
loadHistory();

"JavaScript 学習"

JavaScript #7:電卓に履歴機能を追加する

公開:2026.05.09(土) 03:04

電卓に履歴機能を追加する

JavaScript #6:自作の処理を別ファイルにする」で作成した電卓に計算履歴を表示する機能を追加してみる。

追加する機能:
・計算するたびに、結果を history という配列(リスト)に追加
・配列の中身を、HTMLのリスト(
    など)として画面に表示

    1. index.html修正内容
    ・履歴を表示する領域 id=history-container 追加
    ・履歴を表示する ulノード id=history-list 追加
    ・履歴をクリアするボタン id=clear-history 追加
    <div id="history-container">
      <h3>計算機能</h3>
      <ul id="history-list"></ul>
      <button id="clear-history">履歴をクリア</button>
    </div>
    2. main.js修正内容
    ・履歴を格納するための historyData配列 を追加
    ・"="の処理で historyData配列 へ値の追加と liノードの追加
    // 履歴を表示するulノード
    const historyList = document.getElementById('history-list');
    
    // 履歴を格納するための historyData配列 を追加
    let historyData = [];
     :
    // "="の処理で historyData配列 へ値の追加と liノードの追加
    const expression = display.value;
    const result = calculate(display.value);
    
    if (result !== 'Error') {
        historyData.unshift(`${expression} = ${result}`);
        renderHistory();
    }
    display.value = result;
    
    ・履歴をクリアする id=clear-history ボタンと処理を追加
    // 履歴をクリアするボタン
    const clearHistoryBtn = document.getElementById('clear-history');
    
    // 履歴クリア処理
    function renderHistory() {
        historyList.innerHTML = '';
    
        historyData.forEach(item => {
            const li = document.createElement('li');
            li.textContent = item;
            historyList.appendChild(li);
        });
    }
    
    //  履歴をクリアボタンにイベント登録
    clearHistoryBtn.addEventListener('click', () => {
        historyData = [];
        renderHistory();
    });

    3. style.css修正内容
    履歴クリア用のスタイルを追加
    #history-container {
        margin-top: 20px;
        background: white;
        padding: 15px;
        border-radius: 10px;
        width: 300px;
        box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    }
    
    #history-list {
        list-style: none; /* 点を消す */
        padding: 0;
        max-height: 200px; /* 長くなったらスクロール */
        overflow-y: auto;
    }
    
    #history-list li {
        padding: 8px;
        border-bottom: 1px solid #eee;
        font-family: monospace;
    }
    
    #clear-history {
        margin-top: 10px;
        width: 100%;
        background-color: #ff4444;
        color: white;
        border: none;
        padding: 5px;
        cursor: pointer;
        border-radius: 4px;
    }

参考(全体ソース)

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Vite 電卓</title>
  </head>
  <body>
    <div id="app">
      <!-- ここに電卓のHTMLを貼り付けます -->
      <div id="calculator">
          <input type="text" id="display" readonly>
          <div class="buttons">
              <button>7</button><button>8</button><button>9</button><button>/</button>
              <button>4</button><button>5</button><button>6</button><button>*</button>
              <button>1</button><button>2</button><button>3</button><button>-</button>
              <button>0</button>
              <button>C</button>
              <button>=</button>
              <button>+</button>
          </div>
      </div>
      <div id="history-container">
        <h3>計算機能</h3>
        <ul id="history-list"></ul>
        <button id="clear-history">履歴をクリア</button>
      </div>
    </div>
    <script type="module" src="./src/main.js"></script>
  </body>
</html>

2. main.js
import './style.css'
import { calculate, clearDisplay } from './calculatorLogic.js'
 
const display = document.getElementById('display');
const buttons = document.querySelectorAll('#calculator .buttons button');
// 履歴を表示するulノード
const historyList = document.getElementById('history-list');
// 履歴をクリアするボタン
const clearHistoryBtn = document.getElementById('clear-history');

// 履歴を格納するための historyData配列 を追加
let historyData = [];

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.textContent;
 
        if (value === 'C') {
            display.value = clearDisplay();
        } else if (value === '=') {
            // "="の処理で historyData配列 へ値の追加と liノードの追加
            const expression = display.value;
            const result = calculate(display.value);

            if (result !== 'Error') {
                historyData.unshift(`${expression} = ${result}`);
                renderHistory();
            }
            display.value = result;
        } else {
            display.value += value;
        }
    });
});

// 履歴クリア処理
function renderHistory() {
    historyList.innerHTML = '';

    historyData.forEach(item => {
        const li = document.createElement('li');
        li.textContent = item;
        historyList.appendChild(li);
    });
}

//  履歴をクリアボタンにイベント登録
clearHistoryBtn.addEventListener('click', () => {
    historyData = [];
    renderHistory();
});

3. style.css
body {
    display: flex;
    justify-content: center; /* 横方向の中央 */
    align-items: center;    /* 縦方向の中央 */
    height: 100vh;         /* 画面いっぱいの高さ */
    background-color: #f0f0f0;
    margin: 0;
}
 
#calculator {
    background-color: #333;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.3);
}
 
/* 表示画面のスタイル */
#display {
    width: 100%;
    height: 50px;
    font-size: 24px;
    text-align: right;
    margin-bottom: 10px;
    padding: 10px;
    box-sizing: border-box; /* パディングを含めたサイズ計算 */
    border: none;
    border-radius: 5px;
}
.buttons {
    display: grid;
    /* 4つの列を同じ幅(1fr)で作る */
    grid-template-columns: repeat(4, 1fr); 
    /* ボタン同士の隙間 */
    gap: 10px;
}
 
button {
    padding: 20px;
    font-size: 18px;
    cursor: pointer;
    border: none;
    border-radius: 5px;
    background-color: #eee;
    transition: background-color 0.2s; /* ホバー時のアニメーション */
}
 
/* マウスが乗った時 */
button:hover {
    background-color: #ddd;
}
 
/* 計算ボタンなどの色を変える(お好みで) */
button:nth-child(4n) {
    background-color: #ff9500;
    color: white;
}
.wide {
    grid-column: span 2;
}

#history-container {
    margin-top: 20px;
    background: white;
    padding: 15px;
    border-radius: 10px;
    width: 300px;
    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}

#history-list {
    list-style: none; /* 点を消す */
    padding: 0;
    max-height: 200px; /* 長くなったらスクロール */
    overflow-y: auto;
}

#history-list li {
    padding: 8px;
    border-bottom: 1px solid #eee;
    font-family: monospace;
}

#clear-history {
    margin-top: 10px;
    width: 100%;
    background-color: #ff4444;
    color: white;
    border: none;
    padding: 5px;
    cursor: pointer;
    border-radius: 4px;
}

"JavaScript 学習"

JavaScript:学習記事一覧

更新:2026.05.10(日) 13:34
公開:2026.05.09(土) 01:39

JavaScript 学習記事一覧



"JavaScript 学習"

JavaScript #6:自作の処理を別ファイルにする

公開:2026.05.07(木) 20:33

JavaScriptで自作の処理を別ファイルにしてimportしてみる

前回記事:「JavaScript #5:電卓アプリをVite対応にする」の続き。
自作の処理を別ファイルに切り出して import する、という工程にステップアップしてみる。
今回の目標は、電卓の計算ロジックだけを calculatorLogic.js という別ファイルに分離すること。

1. calculatorLogic.js作成
calc-vite\src\calculatorLogic.js ファイルを新規作成
// calculatorLogic.js の先頭に必要です
import { evaluate } from 'mathjs';

export function calculate(expression) {
    try {
        return evaluate(expression); // window.math ではなく直接 evaluate を使う
    } catch (error) {
        console.error("計算エラー:", error); 
        return 'Error';
    }
}

export function clearDisplay() {
    return '';
}
    

2. main.js修正
calc-vite\src\main.js ファイルを修正、
calculatorLogic.jsを読み込むように変更する。
import './style.css'
// 自作ファイルから特定の関数をインポート({ } を使う!)
import { calculate, clearDisplay } from './calculatorLogic.js'

const display = document.getElementById('display');
const buttons = document.querySelectorAll('button');

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.textContent;

        if (value === 'C') {
            display.value = clearDisplay();
        } else if (value === '=') {
            display.value = calculate(display.value);
        } else {
            display.value += value;
        }
    });
});
    

"JavaScript 学習"

JavaScript #5:電卓アプリをVite対応にする

公開:2026.05.07(木) 09:37

電卓アプリをVite対応にする

以下記事で作成した簡易電卓をVite対応に変更してみる。 ※ JavaScript #2:簡単な電卓を作る
JavaScript #3:ライブラリを使ってみる
JavaScript #4:ビルドツールについて

1. index.htmlの編集
calc-vite\index.htmlを編集する。
主なポイントは、
・styleはstyle.cssに記載するのですべて削除
 style.cssの読み込みもmain.jsで行うので記載しない
・jsはmain.jsに記載するのですべて削除
 main.jsを読み込むようにする。
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Vite 電卓</title>
  </head>
  <body>
    <div id="app">
      <!-- ここに電卓のHTMLを貼り付けます -->
      <div id="calculator">
          <input type="text" id="display" readonly>
          <div class="buttons">
              <button>7</button><button>8</button><button>9</button><button>/</button>
              <button>4</button><button>5</button><button>6</button><button>*</button>
              <button>1</button><button>2</button><button>3</button><button>-</button>
              <button>0</button>
              <button>C</button>
              <button>=</button>
              <button>+</button>
          </div>
      </div>
    </div>
    <script type="module" src="./src/main.js"></script>
  </body>
</html>      
    

2. main.jsの編集
calc-vite\src\main.jsを編集する。
主なポイントは、
・style.cssもimportで読み込む
・math.jsをimportして使う
import './style.css'
import { evaluate } from 'mathjs'

const display = document.getElementById('display');
const buttons = document.querySelectorAll('button');

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.textContent;

        if (value === 'C') {
            display.value = '';
        } else if (value === '=') {
            try {
                // インポートした evaluate 関数を使う
                display.value = evaluate(display.value);
            } catch (e) {
                display.value = 'Error';
            }
        } else {
            display.value += value;
        }
    });
});    
    

3. style.cssの編集
calc-vite\src\style.cssを編集する。
body {
    display: flex;
    justify-content: center; /* 横方向の中央 */
    align-items: center;    /* 縦方向の中央 */
    height: 100vh;         /* 画面いっぱいの高さ */
    background-color: #f0f0f0;
    margin: 0;
}

#calculator {
    background-color: #333;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.3);
}

/* 表示画面のスタイル */
#display {
    width: 100%;
    height: 50px;
    font-size: 24px;
    text-align: right;
    margin-bottom: 10px;
    padding: 10px;
    box-sizing: border-box; /* パディングを含めたサイズ計算 */
    border: none;
    border-radius: 5px;
}
.buttons {
    display: grid;
    /* 4つの列を同じ幅(1fr)で作る */
    grid-template-columns: repeat(4, 1fr); 
    /* ボタン同士の隙間 */
    gap: 10px;
}

button {
    padding: 20px;
    font-size: 18px;
    cursor: pointer;
    border: none;
    border-radius: 5px;
    background-color: #eee;
    transition: background-color 0.2s; /* ホバー時のアニメーション */
}

/* マウスが乗った時 */
button:hover {
    background-color: #ddd;
}

/* 計算ボタンなどの色を変える(お好みで) */
button:nth-child(4n) {
    background-color: #ff9500;
    color: white;
}
.wide {
    grid-column: span 2;
}
    

これで電卓が動作する。

"JavaScript 学習"

JavaScript #4:ビルドツールについて

公開:2026.05.06(水) 23:45

JavaScriptのビルドツール

Web開発における「ビルド」とは、「開発者が書きやすいコード」を「ブラウザが読みやすいコード」に変換・最適化する工程のこと、らしい。

なぜビルドが必要なのか?
現代のWeb開発では、ブラウザが直接理解できない技術をたくさん使用する。
・ TypeScript: ブラウザは実行できないので、JavaScriptに変換する必要がある。
・ モジュール管理: 多くのライブラリ(math.jsなど)を組み合わせて使う際、バラバラのファイルを1つにまとめた方が
読み込みが速い。
・ 最適化: コード内の不要な改行やスペースを削り、ファイルサイズを極限まで小さくする(Minify)。

トレンドのツール:Vite(ヴィート)らしい。

前回作成した簡易電卓(JavaScript #3:ライブラリを使ってみる) をViteを使ったプロジェクトへアップグレードしてみる。

1. Viteプロジェクトの作成
既存の ~/docker/node.js フォルダで作業しても良いが、新しく calc-vite というプロジェクトを作ることにする。
WSL(Ubuntu)で以下コマンドを実行
質問はすべてEnterで進める。
docker compose exec app npm create vite@latest calc-vite -- --template vanilla

※ --template vanilla … ReactやVueといったフレームワークを使わない、純粋なJavaScriptプロジェクトを作成

実行結果:
xxx@xxx:~/docker/node.js$ docker compose exec app npm create vite@latest calc-vite -- --template vanilla
Need to install the following packages:
create-vite@9.0.6
Ok to proceed? (y)


> app@1.0.0 npx
> create-vite calc-vite --template vanilla

│
◇  Install with npm and start now?
│  Yes
│
◇  Scaffolding project in /app/calc-vite...
│
◇  Installing dependencies with npm...

added 15 packages, and audited 16 packages in 8s

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
│
◇  Starting dev server...

> calc-vite@0.0.0 dev
> vite


  VITE v8.0.10  ready in 269 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
    
Viteの画面で止まるのでCTRL+Cで終了。
プロジェクトディレクトリ配下に calc-vite フォルダが作成される。

2. フォルダ構成の変更
プロジェクトフォルダの compose.yaml の volumes 設定を変更し、新しいプロジェクトフォルダをマウントするようにする。
services:
  app:
    image: node:20-slim
    user: "node"
    volumes:
      - ./calc-vite:/app  # 作成したプロジェクトフォルダをマウント
    working_dir: /app
    ports:
      - "5173:5173"       # Viteのデフォルトポートに変更
    command: npm run dev  # Viteの開発用サーバーを起動
    tty: true      
    

Viteはコンテナ外からの接続を許可していないらしく、WindowsからViteにアクセスできない。
"npm run dev"した場合はWindowsからでもアクセスできるように calc-vite\package.json の以下設定を変更する。
    "dev": "vite --host",
    

3. 初期セットアップと起動
設定を書き換えたら、以下の手順でコンテナを再起動し、必要なライブラリをインストールする。
# 一旦止めて再起動
docker compose down
docker compose up -d

# ライブラリのインストール
docker compose exec app npm install

# 再度 mathjs をインストール
docker compose exec app npm install mathjs

実行結果:
xxx@xxx:~/docker/node.js$ docker compose down
[+] down 2/2
 ✔ Container nodejs-app-1 Removed                                                                       1.0s
 ✔ Network nodejs_default Removed                                                                       0.2s
xxx@xxx:~/docker/node.js$ docker compose up -d
[+] up 2/2
 ✔ Network nodejs_default Created                                                                       0.0s
 ✔ Container nodejs-app-1 Started                                                                       0.2s
xxx@xxx:~/docker/node.js$ docker compose exec app npm install

added 2 packages, and audited 18 packages in 766ms

9 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
xxx@xxx:~/docker/node.js$ docker compose exec app npm install mathjs

added 10 packages, and audited 28 packages in 1s

11 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
    

4. 動作確認
Windowsでブラウザを起動し http://localhost:5173 へアクセスしViteの初期画面が表示されればOK

5. Viteプロジェクトのファイル構成
Viteプロジェクトフォルダの主要はフォルダ・ファイル
・ index.html:アプリの入り口
・ main.js:プログラムのメイン処理。VB.NETの Main() メソッドに近い役割
・ style.css: デザイン(CSS)を書く場所
・ public/ フォルダ: 画像など、そのまま公開したいファイルを置く場所

"JavaScript 学習"

JavaScript #3:ライブラリを使ってみる

公開:2026.05.06(水) 08:02

JavaScript ライブラリを使ってみる

前回作成した簡易電卓(JavaScript #2:簡単な電卓を作る)では、JavaScriptの eval関数 というのを使っていたが、これを mach.jsというパッケージの math.evaluate に変更してみる。

1. 変更によるメリット
・安全:alert() などの不正なスクリプトを実行しようとしても、math.jsでは実行されない。
・高機能: 単なる四則演算だけでなく、sin(45 deg) や sqrt(16) といった関数も文字列として渡せば計算できる。
・誤差への強さ: JavaScript 標準の計算よりも数値の扱いが正確になる。

2. math.jsライブラリインストール
WSL(Ubuntu)でプロジェクトの作業ディレクトリ上で以下コマンドを実行しインストールする。
docker compose exec app npm install mathjs

実行結果:
xxx@xxx:~/docker/node.js$ docker compose exec app npm install mathjs

added 10 packages, and audited 96 packages in 2s

28 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities        
      
これで node_modules フォルダの中に math.js の本体が入り、package.json に「このプロジェクトは mathjs を使います」という記録が残る。

3. ライブラリ読み込み
index.html の <script> タグの周辺を以下を追加する。
<script src="./node_modules/mathjs/lib/browser/math.js"></script>

4. ライブラリの使用
"display.value = eval(display.value);" をライブラリの関数に変更
const result = math.evaluate(display.value);
display.value = result;

5. フォルダ構成
ライブラリをインストールしたことにより以下のフォルダ・設定が追加される。
・ package.json の dependencies という項目に mathjs が追加
・ node_modules フォルダに mathjs というフォルダが追加

"JavaScript 学習"

JavaScript #2:簡単な電卓を作る

公開:2026.05.05(火) 09:13

JavaScriptで簡単な電卓を作る

1. 環境

DockerでNode.js環境を作っておく

2. HTMLの作成

body内に結果を表示するtext(id=display)と、計算ボタンを16個作成する。
<div id="calculator">
    <input type="text" id="display" readonly>
    <div class="buttons">
        <button>7</button><button>8</button><button>9</button><button>/</button>
        <button>4</button><button>5</button><button>6</button><button>*</button>
        <button>1</button><button>2</button><button>3</button><button>-</button>
        <button>0</button><button>C</button><button>=</button><button>+</button>
    </div>
</div>
    

3. デザイン

index.htmlの <head> タグ内に <style> タグを追加しCSSコードを記述する。

1. body
body {
    display: flex;
    justify-content: center; /* 横方向の中央 */
    align-items: center;    /* 縦方向の中央 */
    height: 100vh;         /* 画面いっぱいの高さ */
    background-color: #f0f0f0;
    margin: 0;
}
      
2. #calculator (電卓全体)
#calculator {
    background-color: #333;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 10px 25px rgba(0,0,0,0.3);
}
      
3. #display (結果表示欄)
#display {
    width: 100%;
    height: 50px;
    font-size: 24px;
    text-align: right;
    margin-bottom: 10px;
    padding: 10px;
    box-sizing: border-box; /* パディングを含めたサイズ計算 */
    border: none;
    border-radius: 5px;
}
      
4. .buttons (ボタン全体)
.buttons {
    display: grid;
    /* 4つの列を同じ幅(1fr)で作る */
    grid-template-columns: repeat(4, 1fr); 
    /* ボタン同士の隙間 */
    gap: 10px;
}
      
5. button (ボタン)
button {
    padding: 20px;
    font-size: 18px;
    cursor: pointer;
    border: none;
    border-radius: 5px;
    background-color: #eee;
    transition: background-color 0.2s; /* ホバー時のアニメーション */
}
/* マウスが乗った時 */
button:hover {
    background-color: #ddd;
}
/* 計算ボタンなどの色 (左から4つめのボタンの色) */
button:nth-child(4n) {
    background-color: #ff9500;
    color: white;
}
      

4. JavaScriptコード

index.htmlの </body> の直前に <script> タグを追加しJavaScriptコードを記述する。
<script>
    const display = document.getElementById('display');
    const buttons = document.querySelectorAll('button');

    buttons.forEach(button => {
        button.addEventListener('click', () => {
            const value = button.textContent;

            if (value === 'C') {
                display.value = ''; // クリア
            } else if (value === '=') {
                try {
                    display.value = eval(display.value);
                } catch {
                    display.value = 'Error';
                }
            } else {
                display.value += value; // 数字や記号を連結
            }
        });
    });
</script>
    

5. 完成


"JavaScript 学習"

JavaScript #1:node環境の構築

公開:2026.05.03(日) 19:36

JavaScriptの開発環境をDockerで構築する

JavaScriptの学習をするため、Docker上にnode.js環境の構築をすることにした。

Docker環境

1. Windows+WSL+Ubuntu上にDockerを構築


2. 作業フォルダ作成

WSL上に "~/docker/node.js" フォルダを作成した。
mkdir -p ~/docker/node.js
cd ~/docker/node.js

3. compose.yamlファイル作成

VSCodeを起動
xxx@xxx:~/docker/node.js$ code .

compose.yaml
services:
  app:
    image: node:20-slim
    volumes:
      - .:/app
    working_dir: /app
    ports:
      - "3000:3000"
    tty: true

4. コンテナ起動

WSLターミナル、またはVSCodeのターミナル(CTRL+@)で以下コマンドを実行
docker compose up -d

実行結果:
xxx@xxx:~/docker/node.js$ docker compose up -d
[+] up 10/10
 ✔ Image node:20-slim     Pulled                                                                                   11.1s
 ✔ Network nodejs_default Created                                                                                   0.1s
 ✔ Container nodejs-app-1 Started

5. 簡易サーバー起動

コンテナ上で簡易サーバーを起動
docker compose exec app npx serve .

実行結果:
xxx@xxx:~/docker/node.js$ docker compose exec app npx serve .
Need to install the following packages:
serve@14.2.6
Ok to proceed? (y) y

 ERROR  Cannot copy server address to clipboard: Couldn't find the `xsel` binary and fallback didn't work. On Debian/Ubuntu you can install xsel with: sudo apt install xsel.

   ┌────────────────────────────────────────┐
   │                                        │
   │   Serving!                             │
   │                                        │
   │   - Local:    http://localhost:3000    │
   │   - Network:  http://172.19.0.2:3000   │
   │                                        │
   └────────────────────────────────────────┘

 HTTP  5/3/2026 11:52:10 AM 172.19.0.1 GET /
 HTTP  5/3/2026 11:52:10 AM 172.19.0.1 Returned 200 in 22 ms
 HTTP  5/3/2026 11:52:10 AM 172.19.0.1 GET /favicon.ico
 HTTP  5/3/2026 11:52:10 AM 172.19.0.1 Returned 404 in 3 ms
 HTTP  5/3/2026 11:52:14 AM 172.19.0.1 GET /
 HTTP  5/3/2026 11:52:14 AM 172.19.0.1 Returned 200 in 1 ms
ERRORと表示されているがxselが入っていないのが原因で特に問題ないらしい

6. 動作テスト

WSLの作業フォルダ上にindex.htmlを作成
VSCodeでは "!" + Enter(または "html:5" + Enter)でhtmlのテンプレートを作成
bodyに適当に文字列を入力しておく。

Windowsのブラウザで「http://localhost:3000」にアクセス、index.htmlの中身が表示されればOK

簡易サーバーは CTRL+D で終了させておく、

7. package.jsonの作成

"npm start" コマンドで簡易サーバーを起動できるようにpackage.jsonを作成する。
WSLにて以下コマンドを実行する。
docker compose exec app npm init -y
docker compose exec app npm install serve

実行結果:
xxx@xxx:~/docker/node.js$ docker compose exec app npm init -y
Wrote to /app/package.json:

{
  "name": "app",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}



xxx@xxx:~/docker/node.js$ docker compose exec app npm install serve

added 85 packages, and audited 86 packages in 2s

26 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

package.jsonはWSL(Ubuntu)の作業用フォルダに作成されており、これを編集したいが書き込み権限が無く編集できない。
WSL(Ubuntu)の作業フォルダ上で以下コマンドを実行し権限を付与する。
sudo chown -R \$USER:$USER .

次にWSLで "code package.json" (またはWindowsのVSCodeからリモートエクスプローラー、もしくは Ubuntu上でvimで) scriptsの部分に "start: serve ." を付加する。
{
  "name": "app",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "serve ."
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
    "serve": "^14.2.6"
  }
}
これで以下コマンドで簡易サーバーが起動できるようになる。
docker compose exec app npm start

8. コンテナを一般ユーザーで動かす

コンテナ内の動作はコンテナ内のrootユーザーによって動作するため、先ほどのpackage.jsonのようにホストから編集できないファイルが作成される場合がある。
"node:20-slim"イメージには nodeという名前の一般ユーザーが含まれており、このユーザーでコンテナを動かすことでこのトラブルを防ぐことができる。
"node"ユーザーでコンテナを動かすには compose.yaml に "user" 設定を追加する。
services:
  app:
    image: node:20-slim
    user: "node"  # ← これを追加(rootではなく標準ユーザーnodeで動かす)
    volumes:
      - .:/app
    working_dir: /app
    ports:
      - "3000:3000"
    tty: true
設定を反映するには、CTRL+C および compose down でコンテナをいったん停止し compose up で再起動する。
docker compose down
docker compose up -d

9. コンテナ起動時に簡易サーバーも起動させる

現在はコンテナ起動したとに docker compose exec app npm start を実行する必要がる。
コンテナ起動時に npm start を実行させるには compose.yaml に "command" の設定を追加する。
services:
  app:
    image: node:20-slim
    user: "node"
    volumes:
      - .:/app
    working_dir: /app
    ports:
      - "3000:3000"
    # コンテナ起動時に自動で実行されるコマンド
    command: npm start
    tty: true
"docker compose down" → "docker compose up -d" でコンテナを再起動、
Windowsからブラウザで "localhost:3000" にアクセスできれば無事に起動できている。

"JavaScript 学習"

Link:ECMAScriptで学ぶ正規表現

(2024.04.09 05:12)

ECMAScriptで学ぶ正規表現


学習リンク

JavaScriptで正規表現 (1)


JavaScriptで正規表現

JavaScript(ECMAScript)で正規表現を使う方法のまとめ

・ECMAScriptで正規表現を使うには「RegExp」クラス、「String」クラスの一部のメソッドを使う

・RegExpクラスを使うには3つの方法がある

1. コンストラクタにマッチングパターン、フラグを指定
※作成されるたびにコンパイル (ループ中でパターンが変換する場合に使う)
const regex = new RegExp('パターン'); // RegExp('oo');
const regex = new RegExp('パターン', 'フラグ'); // RegExp('oo', 'g');

2. リテラル記法 (一般的な使い方)
※評価時にコンパイル (ループ中で毎回同じパターンを使う場合は効率が良い)
const regex = /パターン/; // regex = /oo/';
const regex = /パターン/フラグ; // regex = /oo/g;

3. コンストラクタを介したリテラル記法
const regex = new RegExp(/パターン/); // RegExp(/oo/);
const regex = new RegExp(/パターン/, 'フラグ'); // RegExp(/oo/, 'g');

・testメソッド (マッチングするか調べる)
const regex = /[\d]{4}/; // 4桁の数字
const str = '225-0002';
console.log(regex.test(str)); // true

・execメソッド (マッチングした文字列を取り出す)
const regex = /[\d]{4}/;
const str = '225-0002';
const array = regex.exec(str);
if (array !== null) {
 console.log('${array[0]}'); // 0002
}

・Stringクラス+matchメソッド (マッチングした文字列を配列で取得)
const regex = /[\d]{3,4}/g;
const str = '225-0002';
const array = str.match(regex);
if (array !== null) {
 console.log(array); // ['225', '0002']
}

・Stringクラス+matchAllメソッド (マッチングした文字列を反復子で取得)
※gフラグを指定すること
const regex = /[\d]{3,4}/g;
const str = '225-0002';
const array = str.matchAll(regex);
for (const match of array) {
console.log(match[0]); // 225 と 0002
}

・Stringクラス+searchメソッド (マッチングした文字列の位置)
※先頭は0、ヒットしなければ-1
const str = '225-0002';
const regex1 = /[\d]{4}/;
console.log(str.search(regex1)); // 4
const regex2 = /[\d]{5}/;
console.log(str.search(regex2)); // -1

・Stringクラス+replaceメソッド (マッチングした文字列を別の文字列に置き換え)
※gフラグを指定するとマッチングした全ての文字列を置換
const regex = /[\d]{4}/;
const str = '225-0002-0003';
console.log(str.replace(regex, '9999')); // 225-9999-0003
const regex2 = /[\d]{4}/g;
console.log(str.replace(regex2, '9999')); // 225-9999-9999

・Stringクラス+replaceAllメソッド (マッチングした文字列を全て置換)
※gフラグを指定すること
const regex = /o{2}/g;
const str = 'Boo Foo Woo';
console.log(str.replaceAll(regex, 'ee')); // Bee Fee Wee


JavaScript, 正規表現

JavaScript:ダブルバン?


!! (ダブル バン?)

JavaScriptで ! (exclamation 感嘆符 ビックリマーク エクスクラメーション マーク)を2つ繋げた記述を見かけた。

FirebaseWebコードラボ
return !!getAuth().currentUser;

何を意味しているのか良くわらかなったが、以下の説明によると
値があれば true、値が無ければ(nullなどであれば)falseを返すっぽい
Javascript「バン、バン。IShotYouDown」-Javascriptでのダブルバング(!!)の使用。| パトリック・ディバインより良い

上記サイトでは ! を2つ書くことを Double Bang と呼んでいた


JavaScript, Tips

書籍:JavaScriptプログラマのためのWebデザイン入門


JavaScriptプログラマのためのWebデザイン入門

タイトルJavaScriptプログラマのためのWebデザイン入門
Web design Primer for JavaScript Programmer
著者葛西秋雄/著
喜安亮介/著
出版者東京 秀和システム
出版年2010.9
形態事項14,225p 24cm
ISBN978-4-7980-2726-5
価格(本体価格 \2800)
NDC10(NDC9)007.645 (547.4833)
予約日2021.11.15(月)
取得日2021.11.19(金)


書籍

その他の記事