初版作成 2018.1.27
最終更新 2024.07.08
html ファイルの内容を動的に書き換えるためにある。
下記のように、スクリプトを書く。 body の中に書いてもよい。 <html> <head> <title>タイトル</title> <script> ここにスクリプトを書く。 </script> </head> <body> </body> </html>
通常状態では、ブラウザにエラーは表示されない。 デバッグモードにする必要がある。 Chrome が使いやすい。 F12 を押すとデバッグ領域が表示される。 console タブにエラーが表示される。 Excel VBA のイミディエイトウィンドウのように、 console.log("a = %d",a) で console に出力することができる。 alert("文字列") でメッセージボックスを作成して出力する 方法もある。
・関数名と変数名は同じ名前を使えない!!! これでハマることが多いので注意! ・大文字小文字の区別がある innerHTML を間違えて innerHtml と書いてしまうと、 何も起こらない。
「古い JavaScript」は変数宣言不要。 プログラム先頭に 'use strict'; と書くと、「新しい JavaScript」を実行するモードになり、 変数宣言が必須となる。 ----------- 整数と実数の区別はない。 変数に型はないが、Excel のセルように、中に入っている データは型を持つ。例えば「数値」「文字列」「オブジェクト」 a = 123; b = "123"; document.write("型は " +(typeof a)); id はグローバル変数と同じらしい。 id と同一の変数名を使用すると、プログラムは実行可能なので、 バグの原因となる。 ハイフンは通常の変数には使えないが、id には使えるので、 message1 = document.getElementById("id-message1"); のように、id にはハイフンを入れた文字列を使うと良いと思われる。
・トップレベルで宣言した変数はグローバル ・関数内で宣言した変数は関数内ローカル 変数宣言には var, let, const の 3 種類がある。 ・let は関数ローカルな変数 ・const は再代入不可 ・var は古い仕様なので、使う必要はない。 var と let は少しスコープが異なる。var はどこで宣言しても その関数内ローカル。let は if や for のブロック内で宣言 したとき、そのブロック内ローカル ● C の static 関数の中に関数を書くことができる。 function parent(){ let a = 1; child(); alert(a); // a は 2 になっている function child(){ a = 2; } } 以下のように書くと 変数 a は関数 parent, child1, child2 のみで使える。 parent は宣言だけにしておくと、C の static のような 感じで使える。 function parent(){ let a; function child1(){ } function child2(){ } }
プロパティを間違えてもエラーは起こらない。 例えば obj.style.backgroundColor = "red" を obj.style.backgroundColo = "red" と間違えると何も起こらない。 デバッガにもエラーが表示されないので、 この手の誤りは発見しづらい。
if, for, while は C と全く同じ ループからの脱出も C と同じく break, continue ラベル付きの break により多重ループから一気に脱出可能。 ラベルの位置に注意! 脱出するループの for 文の手前に書かないとエラーになる label1: for(i = 0; i < 4; i++){ for(j = 0; j < 4; j++){ document.write("i j = " + i + " " + j + " "); if ( i == 2 && j == 1 ) { break label1; } } }
文字型は "abc" 'abc' どちらも可 数値型と文字列型の変換 num = 123; str = String(num); str = num.toString(); str = "123"; num = Number(str); // str に数値以外の文字が含まれていると NaN num = parseInt(str); // 整数化 数値以外の文字は無視 num = parseFloat(str);// 数値以外の文字は無視
a = 0x1f // 16進 b = 1.2e-4 // 1.2 × 10^(-4)
C++ と同じ // コメント /* コメント */
i = 10; x = 3.4; print "i = " + i + " x = " + x; JavaScript には C の printf に対応する書式付きの print 機能はない。自分で実装する必要がある。 github に sprintf.js というプログラムがある。 https://github.com/alexei/sprintf.js
function rect_area(height, width){ let area; // 関数内だけで使う変数はローカルにする area = height * width; return area; } a = rect_area(2,5); 返り値なしの return 文を使うこともできる (関数の途中で実行を打ち切る場合)。
(1) window.onload を使う方法 <script> window.onload = init; // html ファイル読込終了直後に実行 init() ではエラー function init(){ 初期化処理 } </script> head に書くのと body に書くので、微妙に違うようだが、 よく分からない。 (2) イベント DOMContentLoaded を使う方法 document.addEventListener("DOMContentLoaded", init); function init() { 初期化処理 } 無名関数を使う方法 document.addEventListener("DOMContentLoaded", function() { 初期化処理 });
< グローバル領域 > let p1; < init() の中 > p1 = document.getElementById("id-p1"); p1.innerHTML = "moji"; < body の中 > <p id="id-p1">ここを書き換える</p> <input type="button" value="ボタン上の文字" onclick="start()"> <input type="text" value="デフォルトの文字" onclick="moji()"> 操作する要素は <p> 以外に <span> <div> <canvas> などが考えられる。
p1 = document.getElementById("id-p1"); p1.innerHTML = "<b>moji<b>"; p1.textContent = "<b>moji<b>"; innerHTML は moji が太字で表示される。 textContent は <b>moji<b> と表示される。
str = new String("文字です"); document.write("<p>「" + str + "」の長さは " + str.length + " です。");
obj1 = new Object(); obj1.name = "yabu"; obj1.age = "45"; . の後にプロパティを付け加えることができる。 obj2 = obj1; obj2.name = "mitukuri"; 代入ではなく参照なので obj1.name の結果は "mitukuri" になっている。 以下の 2 つは等価と思われる (1) let pt = new Object(); pt.x = 10; pt.y = 20; (2) let pt; pt = {"x": 10, "y" : 20}; (2) は関数の返り値として以下のように用いることができる。 return {"x": 10, "y" : 20}; ret = func( ); のとき ret.x, ret.y が得られる。
添字が整数の配列 a = new Array(3); 3 を省略してもよい a[0] = "a"; a[1] = "b"; のように宣言なしで書いてもよい。 a[] = "c"; とすると自動的に a[2] に割り当てられる。 いきなり a[3] = "c"; とすると、a[3] のみが生成される。次に a[] = "d"; とすると a[4] に割り当てられる。 b = new Array("yabu", "mitukuri", "sera"); c = ["yabu", "mitukuri", "sera"]; 連想配列 name = new Array(); name["yabu"] = "tetsuro"; name["mitukuri"] = "kazuhiro"; name["sera"] = "keita";
・ボタン <input type="button" value="座標位置更新" onclick="new_points()"> ・文字 数値 <input type="number" id="id-num1" value="10"> <input type="text" id="id-text1" value="abc"> num1 = document.getElementById("id-num1"); num = parseFloat(num1.value); (注意!!) type="number" でも num1.value は文字列である。 parseInt(), parseFloat() で数値化を怠ると、 ひどいバグの原因となる。 a = "5"; b = a * 10; c = a + 10; のとき、b は数値 50, c は文字列 "510" となる。 JavaScript では文字列と数値を演算すると、 掛け算は「文字列が数値に自動型変換」 足し算は「数値が文字列に自動型変換」という 非常にいやらしいことが起こる。 エラーにしてほしい。 text1 = document.getElementById("id-text1"); text = text1.value; ・スライドバー <input type="range" id="id-slidebar" min="0" max="1" step="0.01" value="0"> slidebar1 = document.getElementById("id-slidebar"); slidebar1.addEventListener('change', move_slide); slidebar1.value = 0; ・ラジオボタン <form id="id-radio1"> <input type="radio" name="name1" value="yes"> yes <input type="radio" name="name1" value="no" checked> no </form> radio1 = document.getElementById("id-radio1"); list = radio1.name1; for(i = 0; i < list.length; i++){ if ( list[i].checked == true ){ radio_value = list[i].value; break; } } 以下のように書く方法が簡潔なのだが、 そのように書くと、スライドバーと併用したときに スライドバーを動かすと、ラジオボタンのチェック場所が なぜか移動するという妙な現象が発生した。 よくわからない。 radio_value = list.value;
ボタンを押すと、動的に要素が変化する。 <html> <head> <title>JavaScript の練習</title> <script> let p1, canvas1, dc; window.onload = init; function init(){ p1 = document.getElementById("id-p1"); canvas1 = document.getElementById("id-canvas1"); dc = canvas1.getContext('2d'); } function b1_click(){ p1.innerHTML = "かきくけこ"; } function b2_click(){ canvas1.style.backgroundColor = "rgb(0,255,255)"; dc.beginPath() dc.rect(50,10,100,150); dc.fillStyle = "rgb(255,255,0)"; dc.fill(); } </script> </head> <body> <p>JavaScriptの練習です。</p> <canvas id="id-canvas1" width="300px" height="300px" style="background-color: beige"></canvas> <p> <input type="button" value="ボタン1" onclick="b1_click()"> <input type="button" value="ボタン2" onclick="b2_click()"> </p> <p id="id-p1">表示エリア1</p> </body> </html>
要素を識別するのに id ではなく name を使う方法もある。 name を使うと、複数の要素に同じ name をつけることができ、 getElementsByName() を使うと、配列として得られるらしい。 ただし、<div> には name 属性がないなど、ややこしいので、 name はいざ使うときに調べることにする。
(1) タグ内に直接書き込む方法 <span onclick="func(arg)"> 引数が無い場合は func() と書く。func はダメ。 複数の要素が同じ関数を呼び、呼び元によって 異なった値を関数の引数に加えたいとき、 (1) の形式が良いと思われる。 (2) を使う場合、引数は固定 (event) なので、 要素ごとに別の関数を定義し、 その関数が共通関数を呼ぶ必要がある。 (2) id を使う方法 <span id="span1">この領域</span> obj = document.getElementById("span1"); この方法で呼ばれる関数の引数は固定でイベントの引数が入る。 ユーザーが定義する引数を使うことはできない。 (2a) 無名関数を使う方法 obj.onclick = func1(e){ 処理内容 } (2b) 関数を別の場所で定義する obj.onclick = func2; func2(e){ } (2c) イベントリスナを定義する(この方法が最も分かりやすい) obj.addEventListener("click" ,click); obj.addEventListener("mousemove",move); window.addEventListener("keydown",key); // window はデフォルトで存在する // keydown は window しか受けられない function click(e){ let x = e.offsetX; let y = e.offsetY; } function move(e){ let x = e.offsetX; let y = e.offsetY; } function key(e){ let code = e.keyCode; }
<input type="text" onkeyup="func(arg)" id="text1"> <div onclick="func(arg)" style="background:beige;" id="div1"> obj = document.getElementById("text1"); obj.onmouseover = func1; obj.onmouseout = func2; obj.value = "str" // テキストボックスの内容 obj = document.getElementById("div1"); obj.style.backgroundColor = obj.style.left = // position:absolute が必要 obj.style.top = obj.style.display = "block" or "none" obj.innerHTML = "moji"; // <div> <p> <span> など タグの中に書く時は on が付く。 関数の定義のときもイベントは on がつく。
デフォルトで on になっているので、ヒント機能を テキストボックスに付加するとき <input type="text" id="myid" name="myname" size="5" autocomplete="off">
作成 <canvas id="canvas1" width="300px" height="300px"></canvas> オブジェクトとデバイスコンテキストの取得 canvas = document.getElementById("canvas1"); d = canvas.getContext('2d'); 線を描く d.beginPath(); d.moveTo(x,y); d.lineTo(x2,y2); d.lineTo(x3,y3); d.lineWidth = 5; d.strokeStyle = "rgb(255,0,0)"; d.stroke(); 長方形 d.beginPath(); d.rect(x, y, xlen, ylen); d.fillStyle = "rgb(255,255,0)"; "#ff00aa" も可 d.fill(); d.lineWidth = 1; d.strokeStyle = "rgb(0,0,0)"; d.stroke(); 円(扇形) d.beginPath(); d.arc(x,y,radius,start_angle,end_angle,true); d.fillStyle = "rgb(255,255,0)"; d.fill() d.lineWidth = 10 d.strokeStyle = "rgb(0,255,0)"; d.stroke(); 背景色で塗りつぶす d.clearRect(0,0,300,300); 文字 d.font = '14pt Arial'; d.fillText("abc", x, y) キャンバス上のマウスの位置を取得 canvas.addEventListener("click" ,click); canvas.addEventListener("mousemove",move); function click(e){ let x = e.offsetX; let y = e.offsetY; } function move(e){ let x = e.offsetX; let y = e.offsetY; } キャンバスの左上位置の取得(マウスの相対位置を知るのに使う) let canvas_location = canvas.getBoundingClientRect(); function mouse_move(e){ let cx = e.clientX - canvas_location.left; // マウスの相対位置 x let cy = e.clientY - canvas_location.top; // マウスの相対位置 y }
location.reload();
location.href=(url) url を http:// から始めない場合は、 現在の位置からの相対位置
C 言語の sleep() に相当する機能や Arduino 言語の delay() に 相当する機能は以下のように実現する。 // 関数 sleep を定義 const sleep = ms => new Promise(res => setTimeout(res, ms)); async function yobidasi_moto(){ // 呼び出し元の関数は async をつける await sleep(1000); // sleep には await をつける。 }
setInterval と setTimeout の 2 つの方法がある。 timer_id = setInterval(func1,5000); // func1 を 5000 ms ごとに実行 clearInterval(timer_id); // それを取り消す timer_id = setTimeout(func2,5000); // func2 を 5000 ms 後に実行 clearTimeout(timer_id); // それを取り消す
このサンプルでは web サーバは Raspbery Pi GPIO を使ってハードウェアにアクセスして、 その返答を返してくる。 ---------------- html ファイル ----------------- ------------ head --------- <style> body { font-size: xx-large; margin: 20px; background-color: #ffffd0; } p { line-height: 2.0; } p.button { padding: 0em 0em 1.3em 0em; /* 上 右 下 左*/ } span.blue { background-color: #a0e0ff; padding: 1em 1.5em; /* 上下 左右 */ } </style> ----------- body ------------ <p> <span id="button1" class="blue" onclick="ondo_sokutei()">温度</span> </p> <div style="background-color: beige;"> <p id="ondo_disp"> 温度 = </p> </div> <script type="text/javascript"> let button1, ondo_disp; let xhr, text; button1 = document.getElementById("button1"); ondo_disp = document.getElementById("ondo_disp"); function ondo_sokutei(){ xhr = new XMLHttpRequest(); const file = "cgi-bin/ondo.py"; xhr.open("GET", file, true); xhr.onreadystatechnge = updatePage; xhr.send(null); } function updatePage(){ if ( xhr.status == 200 ){ text = xhr.responseText; } else { text = "status = " + xhr.status; } ondo_disp.innerHTML = text; } </script> ----------------- cgi-bin/ondo.py ---------- #!/usr/bin/python # -*- coding: utf-8 -*- # # apache2: www-data に visudo で権限を与えておくこと # import sys import os import cgi import commands import serial #-------------- 温度測定 ------------- # # root の権限が必要なため ondo_sub.py を使う cmd = "sudo ./ondo_sub.py" ret = commands.getoutput(cmd) #-------------- 結果の送信 ------------ # 最初の 2 行を忘れると apache2 がエラーを出す print "Content-type: text/html" print "" print "温度 = " + ret + " 度" ------------ cgi-bin/ondo_sub.py ------------ #!/usr/bin/python # -*- coding: utf-8 -*- # # シリアル端子の向こう側に Arduino が接続されており、 # Arduino に LM35 が接続されている。 # Arduino から 1 行返答が来る。 # その返答を受けて 1 行標準出力に出力する。 # # GPIO を制御するプログラムは root の権限が必要なので、 # cgi (apache2 の場合 www-data の権限で動作) から sudo で # 本プログラムを呼び出す # import serial vcc = 4.95 rs = serial.Serial('/dev/ttyAMA0', 9600, timeout=10) rs.write("t") line = rs.readline() # 行末は 13 10 rs.close() line = line.rstrip() val = int(line) ondo = val * ( vcc * 1000 / 1024.0 ) / 10 ondo_str = "%5.1f" % (ondo) print ondo_str ----------------------------------------------- arduino のプログラムは これ
d = new Date(); year = d.getFullYear(); month = d.getMonth() + 1; day = d.getDate(); hours = d.getHours(); minutes = d.getMinutes(); seconds = d.getSeconds();
以下のように () で囲むと即座に実行される関数となる。 閉じ括弧の後に、括弧で囲って引数を書く。 (function (arg, arg2){ console.log("引数は " + arg + " と " + arg2 + "です"); })("あい", "abc"); 引数がないときは以下のように空の括弧を書く。 (function (){ console.log("最初に実行する"); })(); ページがロードされたときに実行する初期化用 関数は以下のように書くのが分かりやすいと思う。 window.onload = init(); function init(){ } 以下のように無名関数の即時関数として書いている JavaScript を見たことがある。 (function (){ let global_var; func1(){ } func2(){ } })();