NaNの真実

未定義値の変数を計算、出力しようとすると、NaN(Not a Number)がでます。

typeof NaN === 'Number'   //true (NaNはNumberオブジェクト)
NaN === NaN            //false (NaNは自分自身ではない?)
 NaN ===!NaN          //true (NaNはNaNではないが正解?)
var arg;
var arm = function() {
    arg += 6;
  return arg;
}
alert(arm());

未定義値を代入、参照すると

var arg;
var arm = function() {
    arg += 6;
  return arg;
}
alert(arg);

未定義値(グローバル変数の参照)は、

ドット記法

2.3 オブジェクトのプロパティは、ドット記法もしくはブラケット記法で取得・設定・更新することができます。

// frank オブジェクトを生成

var frank = new Object();
frank.living = true;
frank.age = 56;
frank.gender = 'male';
frank.location = 'Hollywood';
frank.getGender = function() { return frank.gender; };

// プロパティを取得

var str = frank.living + "\n" + frank.age + "\n" + frank.location + "\n" + frank.getGender()
alert(str);

// プロパティを更新

frank.living = false;
frank.age = 99;
frank.gender = 'female';
frank.location = 'Newyork';
frank.getGender = function() { return 'Gender = ' + frank.gender; };
var str = frank.living + "\n" + frank.age + "\n" + frank.location + "\n" + frank.getGender()
 alert(str);

変数の宣言とエラー

今回はJavaScript 第6版』David Flanagan (著),    村上 列 (翻訳)  から予約語、var の省略、値の代入前の変数の参照、変数の上書きなど初歩的なJavaScript の挙動について抜粋しました。(var の語源はvariableからだそうです。)

2.4.1 予約語
JavaScript には予約語がたくさんあります。以下に挙げるような単語は、プログラム中で識別子として使うことはできません。

break delete function return typeof
case do if switch var
catch else in this void
continue false instanceof throw while
debugger finally new true with
default for null try

さらに、以下の単語は、通常のJavaScriptコードでは識別子として使えますが、strictモードの場合は予約語として扱われ識別子には使えません。

implement let private public yield
interface package protected static

JavaScript には、たくさんのグローバル変数や関数があらかじめ定義されています。以下のような定義済みのグローバル変数やグローバル関数と同じ名前を識別子に使うことは避けた方が無難です。

argument encodeURI Infinity Number RegExp
Array encodeURIComponent isFinite Object String
Boolean Error isNaN parseFloat SyntaxError
Date eval JSON parseInt TypeError
decodeURI EvalError Math RangeError undefined
decodeURIComponent function NaN ReferenceError URIError

3.9 変数の宣言

JavaScript で変数の宣言をするには、キーワード var を使います。

var i;
var sum;

複数の変数をカンマ(,)で区切って宣言することもできます。

var i, sum;

for ループやfor/in ループでvar 文を記述することで、ループの一部としてループ変数を宣言することもできます。

for (var i = 0; i < 10; i++) {
  var sum += i;
}
return sum;

もしvar 文で変数の初期値を設定しなかった場合は、宣言された変数は、何か値が代入されるまで undefined(未定義値)になります。

3.9.1 宣言の繰り返しと省略

var 文で宣言されていない変数から値を読みだした場合は、エラーになります。ECMAScript 5 の strict モードでは、宣言されていない変数に対して値を代入してもエラーになります。しかし、歴史的には、つまり非 strict モードでは、宣言されていない変数に対して値を代入した場合、JavaScript はグローバルオブジェクトのプロパティとして変数を作成します。ただし、完全に同じというわけではありません。~(中略)~ つまり、グローバル変数を宣言しなくても問題ないということです。ただし、このようなプログラミングスタイルは決してよいものとは言えません。変数は var を使って宣言するようにしてください。

3.10 変数のスコープ

プログラムのソースコード中における変数の有効範囲をスコープといいます。グローバル変数のスコープは、プログラム全体です。ローカル変数のスコープは、その変数が宣言された関数の中だけに限定されます。関数の中にグローバル変数と同じ名前のローカル変数があった場合は、ローカル変数が優先されます。つまり、グローバル変数と同じ名前でローカル変数や仮引数を宣言すると、グローバル変数が隠されます。

var scope ="global";          // グローバル変数を宣言する。
function checkscope() {
  var scope = "local";        // 同じ名前でローカル変数を宣言する。
  return scope;          // ローカル変数の値が返される。
}
checkscope()                  // => "local"
scope = "global";        // var 文を省略してグローバル変数を宣言する。
function checkscope2() {
  scope = "local";   // あれ!これはグローバル変数を変更したことになる。
  myscope = "local"; // 代入で新たなグローバル変数が暗黙的に宣言。      
  return { scope, myscope }    // 2つの値を返す。
}
checkscope2()                // => {"local","local"}
scope                        // => "local": グローバル変数が変更された。
myscope                // => "local": グローバルな名前空間に追加された。

4.13 関数の定義方法(宣言、式、もしくはコンストラクタ)

// 関数コンストラクタ:最後のパラメータには関数のロジック(関数本体)が入る

var addConstructor = new Function('x',  'y', 'return x + y');

// 関数宣言(function 文)

function addStatement(x, y) {
  return x + y;
}

// 関数式

var addExpression = function(x, y) {
  return x + y;
};

次の例では、foo プロパティをグローバルオブジェクトに格納し、異なるスコープからfoo プロパティにアクセスします。

var foo = 'bar';  // foo はグローバルオブジェクト直下に格納されたグローバル変数
var myApp = function() {  // 関数はスコープを作ることを思い出して
  var run = function() {
    alert(foo);  // 出力: 'bar'
}();
}
myApp();

アナログ時計2

前回のアナログ時計は文字盤が無く、時刻も分かりにくかったのでcanvasに目盛りと文字を追加してみました。

目盛りは、hand関数を利用して円の中心から放射状に60本、幅3px と1px の針を引いて、一回り(10px)小さい半径の円を白で塗りつぶして、らしく見えてきました。時刻を表す文字は、ギリシア数字で適当に配置しています。

https://stuffy.mydns.jp/~gusachan/javascript/clock4.html

参考URL: http://honttoni.blog74.fc2.com/blog-entry-195.html

document.write とinnerHTMLの違い

サンプルは、サイトのリファラをdocument.referrer から取得するスクリプトです。

if (document.referrer.indexOf("http://www.google.co.jp/search?") == 0 {
  var args = document.referrer.substring(ref.indexOf("?")+1).split("&");
  for (var i = 0; i < args.length; i++) {
    if (args[i].substring(0,2) == "q=" ) {
      document.write("<p>Google検索からようこそ!");
      document.write("検索キーワードは:" + 
                 unescape(args[i].substring(2)).replace('+', ' ');
    break;
    }
  }
}

15.10.2

JavaScript の document.write メソッドを使って現在のドキュメントに HTML を出力できるのは、ドキュメントの解析中の間なので注意してください。<scirpt>要素の中のトップレベルのコードから document.write() が呼び出せるのは、このスクリプトがドキュメントの解析の一部として実行されるからです。関数中で document.write() を呼び出すように定義し、イベントハンドラからこの関数を呼び出した場合、予想外の動作をします。このようなメソッドの呼び出しでは、現在のドキュメントが消去され、このドキュメントに含まれていたスクリプト自体も消去されます。~(中略)~ document.write() メソッドは、最近のコードではあまり使われていません。innerHTMLプロパティなどの DOM 機能のほうが、ドキュメントにコンテンツを追加するには便利だからです。

15.5.1

Element の  innerHTML プロパティを読みだせば、マークアップを含んだ文字列形式で、要素のコンテンツが返されます。要素の innerHTML プロパティ に値を設定すると、 Web ブラウザのパーサーが呼び出され、要素の現在のコンテンツは、新たに設定した文字列に対応する表現で上書きされます。名前は、 innerHTML ですが、 innerHTML は HTML 要素だけでなく XML 要素も使えます。
Web ブラウザは、HTML の解釈が得意です。このため、 innerHTML に対して解釈が必要となる値を指定したとしても、かなり効率的に処理されれるのが普通です。ただし、+= 演算子を使って、テキストを少しずつ何度も innerHTML に追加していくことはあまり効率的ではありません。シリアライズ処理と解釈処理を何度も行うことになるからです。

document.write()メソッドも.innerHTMLプロパティも一長一短がありますが、innerHTML の方が融通が利いて危険性も少ないということでしょうか。最新のブラウザではすべて実装されていているそうです。

デジタル時計2

テキストにデジタル時計の簡潔な書き方が載っていたのでご紹介します。toLocaleTimeString(“ja-JP”, options)  locale “ja-JP” は省略可

options には、12時制(true)か24時制(デフォルトまたは未定義ではfalse)の選択をする、hour12 やhour,minute,second(デフォルト、未定義ではnumeric) などがあります。

function displayTime() {
  var elt = document.getElementById('clock');
  var now = new Date();
  elt.innerHTML = now.toLocaleTimeString();
  setTimeout(displayTime, 1000);
}
window.onload = displayTime;

参考URL: https://msdn.microsoft.com/ja-jp/library/474de325(v=vs.94).aspx

JavaScriptの日付メソッド

Date オブジェクトに対して”年”、”月”、”日”を得るには、静的メソッドがそれぞれ用意されています。表にまとめてみました。

Date.getFullYear()
getYear()は推奨されていません。
Date.getMonth()
0から11を返し通常1を足して使います。
Date.getDate()
日にちを数値で返します。
曜日 Date.getDay()
日曜日を0として0から6の数値を返します。

今日の年月日を表示する例を示します。曜日を表示させるには、日~土までの値を入力した配列を作り番号で指定します。

曜日表示にバグがあるらしく、日付表示はtoLocaleDateString() メソッドを使うのが無難みたいです。第1引数にja-JPで西暦、ja-JP-u-ca-japanese で和暦が表示できます。

window.onload = function() {
  var myDate = new Date();
  var options = {
    year: "numeric",
    month: "numeric",
    day: "numeric",
    weekday: "long"
  };
  var str = myDate.toLocaleDateString("ja-JP", options);
  document.getElementById("result").innerHTML = str;
}

ttp://catprogram.hatenablog.com/entry/2015/05/06/143753

デジタル時計

デジタルらしく”0″ を付けました。

window.onload = function() {
  function time() {
    var now = new Date();
    var nowHours = now.getHours();
    var nowMinutes = now.getMinutes();
    var nowSeconds = now.getSeconds();
    if (nowMinutes < 10) nowMinutes = "0" + now.getMinutes();
    if (nowSeconds < 10) nowSeconds = "0" + now.getSeconds();
    strTime = nowHours + ':' + nowMinutes + ':' + nowSeconds;
    document.getElementById('clock').innerHTML = strTime;
  }
  setInterval(time, 1000);
}

GDの描画とテキストの例

PHPの拡張モジュール、GDでも描画関数が用意されており$image=imagecreatefromjpeg(filename) で既存のjpegファイルを読み込めるほか、imageline, imagefilledrectangle, imagearc 関数で線、矩形、円弧などを描画できます。(例:black.php

<?php
$image = imagecreate(200,200);
$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
$black = imagecolorallocate($image, 0x00, 0x00, 0x00);
imagefilledrectangle($image, 50, 50, 150, 150, $black);
imagestring($image, 5, 50, 160,"A Black Box", $black);
header("Content-Type: image/png");
imagepng($image);
?>

imagestringは、imagestring(image, font-id, x, y, text, color) で定義されテキストを画像に追加します。font-idは組み込みのフォントidを[1-5] で指定します。

imagefilledrectangle とimagestring の color パラメータを$black から$white に改変してみます。(例:white.php

<?php
$image = imagecreate(200,200);
$black = imagecolorallocate($image, 0x00, 0x00, 0x00);
$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
imagefilledrectangle($image, 50, 50, 150, 150, $white);
imagestring($image, 5, 50, 160,"A White Box", $white);
header("Content-Type: image/png");
imagepng($image);
?>

PHP リロードしない

Google 先生にPHPでページの自動リロード方法を聞いた処、

<?php
    $rel = $_GET['reload'];
    if ($rel == 'true') {
      header("Location: " . $_SERVER['PHP_SELF']);
    }
    /*デバッグ用*/
    echo($_SERVER['PHP_SELF'].'<br/>');
    echo($_SERVER['SCRIPT_NAME'].'<br/>');
?>

header()を書き込むと良いとのことで試してみましたがダメでした。(たぶん、GETするフラグの作り方が分からないことが分かっている。迷推理)次にJavaScript でリファラを参照して特定のページからアクセスした場合にlocation.reload() するとしてみましたが、何故か無限ループになります。

var myRef = document.referrer;
if (myRef.indexOf("http://hoge.jp/foo.php") == 0) {
  location.reload();
  Object.defineProperty(document,"referrer",{value:"null"});
}

http://oshiete.goo.ne.jp/qa/77766.html で紹介されていた方法で

rload = setTimeout( "location.reload()", 100 );
 clearTimeout( rload );

も試しましたがリロードしませんでした。結局、HTMLで手動リンク

<a href="./bar.php">リロード</a>

が丸いと思いました。(粉ミカン

https://www.ipentec.com/document/document.aspx?page=php-page-reload