初版作成 2018.1.27
最終更新 2025.05.14
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(){
}
})();