変数宣言と再定義について

Posted コメントするカテゴリー: javascript

概要

javascriptでグローバル変数を宣言する時、変数の定義がどのように振舞うのかを調べます。

グローバル変数を生成する際は、グローバルオブジェクトのプロパティが定義されます。
strictモード(‘use strict’)を使わない場合、宣言していない変数に値を代入した瞬間にグローバル変数が作られます。

宣言していない変数とは、具体的には次のような例になります。

//varを使わず、いきなり100を代入(グローバル変数)
test = 100;

上記のように、varによる変数宣言をしない場合は、再定義が可能なプロパティとして生成されます。
また、逆の意味でvarによる変数宣言をする場合は、再定義が不可能なプロパティとして生成されます。

サンプルコード

試しに以下のコードを書きます。

グローバル変数を宣言して生成する場合と、宣言なしで生成する場合の動きの違いがわかります。

//varを使ったグローバル変数へ代入
var test = 10;
console.log(test);

//varを使わず、グローバル変数へ代入
test2 = 20;
console.log(test2);

delete test;
console.log(test);

delete test2;
console.log(test2);

再定義が可能かどうかを調べる為に、delete演算子を使って、それぞれの変数の削除を試みています。

実際に実行した結果は次のようになります。

10
20
10
ReferenceError: test2 is not defined

最後のtest2という変数はdelete演算子によって削除はできません。
これはvar宣言しない場合の変数宣言は再定義可能な(グローバルオブジェクトの)プロパティとして生成されるので、削除ができたということになります。

削除ができた為に、コンソールで出力しようとしたところ、「ReferenceError: test2 is not defined」というエラーになります。

変数宣言についてのまとめ

簡単にまとめると

■var宣言したグローバル変数
再定義不可

■var宣言しないグローバル変数
再定義可能
(delete演算子による削除ができた)

ということになります。

Callオブジェクトについて

Callオブジェクトという概念についてまとめます。

javascriptではグローバル変数はグローバルオブジェクトのプロパティとして解釈されます。
では、ローカル変数の場合はどうなるかと言いますと、関数の呼び出した時に変数オブジェクトが生成されます。
上記の関数を呼び出した時に生成される変数オブジェクトのことをCallオブジェクトと呼びます。

Callオブジェクトは次の情報が含まれています。

関数内のローカル変数の値
関数に渡された引数(名前と値)
引数情報を管理するオブジェクト
thisキーワード

このCallオブジェクトの考え方はスコープチェーンを理解する時に重要になります。

HTMLファイルがUTF-8で書かれていて、画面更新時にはSJISでPOSTする必要がある場合の方法

Posted コメントするカテゴリー: javascript

javascriptの言語仕様の話からは少し逸れますが、webアプリケーションを作成する際、画面遷移時に文字コードの制約がある場合の対応方法を記載します。

具体的にはタイトルの通り、HTMLファイルがUTF-8で書かれていて、画面更新時にはSJISでPOSTする方法です。

<form name="form1" method="post" action="http://xxxxxx/" accept-charset='Shift_JIS'>

<input type="hidden" name="test" value="a">

<input type="submit" value="送信" onClick="buff=document.charset; document.charset='Shift_JIS'; document.form[0].submit(); document.charset=buff;">

</form>

送信ボタンのonClickに文字コードを指定して送信する処理を書くことで、更新時にのみ文字コードを変更して値を送信できます。

決済システム等を実装する際、相手側サーバのAPIがSJISしか受け取れない場合で、なおかつサーバ側言語のフレームワークの制約などで文字コードがSJIS以外で固定されているときに、このように書くケースがあります。

現在アクセスしているURL等を取得する

Posted コメントするカテゴリー: javascript

javascriptをブラウザで実行している際、アクセス時のURL等を取得する方法

console.log("location.href -> " + location.href);
console.log("location.host -> " + location.host);
console.log("location.pathname -> " + location.pathname);
console.log("location.search -> " + location.search);
console.log("location.protocol -> " + location.protocol);
console.log("location.hash -> " + location.hash);
console.log("location.hostname -> " + location.hostname);

locationオブジェクトを使い、任意のプロパティの値を使うと取得可能です。

変数の宣言でデフォルト値を指定する

Posted コメントするカテゴリー: javascript

あまり一般的な書き方ではないかもしれませんが、
javascriptのパイプを利用して、変数のデフォルト値を設定する書き方もあります。

var test = test || "abc";
console.log(test);

出力結果は「abc」となります。

通常ではこのような書き方はあまり見かけませんし、このような書き方はしませんが、動作としてデフォルト値のような振る舞いをします。

javascriptでパイプを2つ書く場合、論理和として判定され、左辺か右辺を両方判定し、論理和を返す動きをします。

この動きを利用して、関数内での変数のデフォルト値を設定するケースがあります。
javascriptならではの書き方かもしれませんが、以下のようなコードになります。

function x(test)
{
	//引数の値がなかった場合、abcとする
	test = test || "abc";
	console.log(test);
}

変数の宣言(その3)

Posted コメントするカテゴリー: javascript

変数を宣言する方法について検証

変数の宣言について、繰り返して宣言した場合の動きを試します。

次のようなコードを書きます。

var test = 10;
var test = 20;
console.log(test);

この場合、特にエラーにならずに処理されます。
コンソールログへは20が出力されます。

次に、varで宣言されていない変数を呼び出してみます。

var test = 30;
var test = 40;
console.log(test2);

この場合は「ReferenceError: test2 is not defined」というエラーになります。
宣言されていない変数に対して、変数の呼び出しはNGです。

では、次のような、変数宣言をしていない変数に代入する場合を試してみます。

var test = 30;
var test = 40;
test3 = 50;
console.log(test3);

この場合、上記のコードのみでしたら、エラーにはなりません。
変数test3への代入は問題なく行われ、コンソールログには50が出力されます。

strict modeについて

また、javascriptにはstrict modeと呼ばれる、実行形態があります。
strict modeはECMAScript2015で導入されて、javascriptを実行するブラウザに厳密な解釈をさせる機能と言えます。
試しに上記のコードの例をstrict modeをつけて実行してみます。

'use strict';
var test = 30;
var test = 40;
test3 = 50;
console.log(test3);

この場合は「ReferenceError: assignment to undeclared variable test3」というエラーになり実行が止まります。

まとめ

ポイントとなる考え方はstrict modeにしない場合、なおかつvarをつけずに変数に代入した場合、エラーにはならなずに処理が続行されます。
この時に使用する変数はグローバルオブジェクトのプロパティして解釈されるので、注意が必要です。
また、グローバル変数のような振る舞いをすることになりますが、javascriptでは基本的にはvarを明記して変数宣言を行うようにします。

変数の宣言(その2)

Posted コメントするカテゴリー: javascript

前回に続きjavascriptの変数宣言について調べます。

変数宣言はvarとletがありますが、宣言の方法を調べてみます。

まずは、変数を単体で宣言する場合は以下のように書きます。

var test;
var a;

など、次に、一度に複数の変数を宣言する場合です。

//1行に書く
var test, a;

次は変数の宣言と同時に値を代入する場合です。

var test = 100;
var a = "1000";

//1行に書いて、なおかつ代入する
var test = 100, a = "1000";

変数宣言はforループ文の内部でも宣言して使用します。

for (var i = 0; i < 100; i++) {
	console.log(i);
}

javascriptでは、宣言された変数に値が代入されない場合は、undefinedと解釈されます。

また、変数を宣言する時に型を指定していません。
型の概念はありますが、明示的に宣言せず、プログラムの処理中に型が動的に決定づけられます。

変数の宣言(var と let)

Posted コメントするカテゴリー: javascript

概要

javascriptにおける変数の宣言を詳しく調べてみます。

本ブログでも以前の投稿(https://propansystem.net/blog/2018/06/20/post-6640/)で、変数の宣言について触れていますが、そもそもjavascriptには歴史的な話としてECMAScript(https://ja.wikipedia.org/wiki/ECMAScript)という名称で標準化されており、ECMAScriptにはバージョンが策定されています。

正式にリリースされているECMAScript2015(2015年に策定)になり、バージョンを省略してES6と呼ぶこともあります。

ES6の前までのバージョンでは、主にvarで宣言していましたが、ES6からはletで宣言することも可能です。

var と letについて

両者の違いは変数スコープの違いがあります。

varの宣言は
以下のような挙動になります。

var test = 10;
console.log(test);

{
	var test = 20;
	console.log(test);
}

console.log(test);

出力結果は

10
20
20

となります。
varで宣言された変数はブラケットで囲んだ後の変数testが20に置き換わっています。

続いて、letでの宣言を試します。

let test2 = 30;
console.log(test2);

{
	let test2 = 40;
	console.log(test2);
}

console.log(test2);

出力結果は

30
40
30

になります。
letで宣言された変数はブラケットの後、変数testの値のが30に置き換わっていません。
このようにletでの宣言は厳密にブラケット内で使うことができ、コーディングの際の不具合の低減につながります。

実装上の留意点

ECMAScriptの策定については、2009年に策定されたEdition5から、2015年以降にEdition6に変わりました。

言語仕様が変わると、ブラウザがそれに対応しているかどうか、といった問題も出てくるので、
一概にjavascript(ECMAScript)のバージョンだけを意識してコーディングができるとも言い切れません。
開発環境や利用環境、全体を見てのコーディングが必要です。

オブジェクトの型変換

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトもまた、型変換ができます。

オブジェクトを型変換する場合、論理値への変換は全てtrueに変換されます。
オブジェクトから文字列、数値への変換はメソッドを呼び出して変換します。

変換するメソッドは

toString()

valueOf()

です。

toStringt()メソッドは各クラスの種類に応じた変換結果を文字列や数値を返します。
valueOf()メソッドについては、各オブジェクトに対しての基本型値に変換したものを返します。

まとめると、以下のようになります。

各オブジェクトの変換について

■オブジェクトを文字列に変換する

①対象となるオブジェクトがtoStringt()メソッドを持つ場合
javascriptはtoStringt()メソッドを呼び出す。
基本型値が返されたら、その値を文字列に変換した文字列を返す。

②toStringt()メソッドが定義されていない場合
基本型値が返されなかった場合は、valueOf()メソッドが定義されているかどうかで、動きが変わってきます。
定義されている場合は、valueOf()メソッドを呼び出します。

③toStringt()メソッドもvalueOf()メソッドも定義されていない場合
例外処理となり、エラーとなります。

■オブジェクトを数値に変換する

①valueOf()メソッドが定義されており、返りの値が基本型値の場合、基本型値を数値に変換して返します。

②toStringt()メソッドが定義されている場合、その値を返します。

③toStringt()メソッドもvalueOf()メソッドも定義されていない場合、例外処理となり、エラーになります。

明示的な型変換

Posted コメントするカテゴリー: javascript

概要

javascriptで明示的な型変換をする場合を試してみます。

明示的な型変換は以下の関数を使います。

Boolean()
Number()
String()
Object()

これらの関数をnew演算子を使わないで呼び出すと、明示的な型変換の動作をします。

簡単な例

次にサンプルコードを書きます。(便宜上consoleに出力しています)

//50
console.log(Number("50"));

//false
console.log(String(false));

//true
console.log(Boolean("60"));

//Number{5}
console.log(Object(5));

コメント部分はそれぞれコンソールに出力された値です。

オペランドと演算の関係

javascriptで、オペランド(被演算子)どうしの演算をする場合、動的な型変換が発生します。

例えば

文字列 + 数値

の場合は、片方の数値が文字列に変換されて、連結されます。

単項演算子の!を使う場合は、論理的に真偽を反転させる為、以下のようになります。

//false
console.log(!10);

//false
console.log(!true);

//true
console.log(!false);

意味の無い実験かもしれませんが、単項演算子!で真偽を反転させたものに、文字列を連結して出力すると、

//falsetest
console.log(!10 + "test");

//falsetest
console.log(!true + "test");

//truetest
console.log(!false + "test");

という結果になりました。

また、単項演算子!の真偽の反転は、2重につけることもできます。
試したところ、それぞれ以下のように出力されます。

//false
console.log(!!false);

//falsetest
console.log(!!false + "test");

Numberクラス

NumberクラスではtoString()メソッドがあります。

ある変数に数値を代入し、toString()メソッドを適用してみます。

この時、メソッドに記述する引数に注目します。
メソッドの引数は2進数から36進数まで、明示的に基数を指定することができます。

それぞれメソッド行末のコメントは実際の出力結果になります。

var test = 65;

//引数を指定しない場合、10進数
console.log(test.toString());       //文字列としての「65」を出力

//2進数として指定
console.log(test.toString(2));      //1000001

//4進数として指定
console.log(test.toString(4));      //1001

//8進数として指定
console.log(test.toString(8));      //101

//10進数として指定
console.log(test.toString(10));     //65

//16進数として指定
console.log(test.toString(16));     //41

//30進数として指定
console.log(test.toString(30));     //25

//36進数として指定
console.log(test.toString(36));     //1t

//(実験的に)37進数として指定
console.log(test.toString(37));

一番最後に実験的に37進数を指定すると

RangeError: radix must be an integer at least 2 and no greater than 36

というエラーになります。

Numberクラスのメソッド

また、Numberクラスには上の例(toString)の他、下記のメソッド(一例です)があります。

toLocalString
toFixed
toExponential
toPercision

詳しく調べていくと、Numberクラスのprototypeには以下のメソッドがあります。

Number.prototype.toExponential()
Number.prototype.toFixed()
Number.prototype.toLocaleString()
Number.prototype.toPrecision()
Number.prototype.toSource()
Number.prototype.toString()
Number.prototype.valueOf()

全てのメソッドの意味と実行結果を確かることはしませんが、全てprototype経由でコールされている点に注意が必要です。

いくつかサンプルを書いてみます。(console.logのコメント部はそれぞれ演算結果です)

//ランダムな数字を代入
var test = 2482704.5681;


//文字列に変換され、小数点は指定の桁数になる
//2482705
console.log(test.toFixed(0));

//2482704.568
console.log(test.toFixed(3));

//2482704.568100
console.log(test.toFixed(6));


//数値が指数表現に変換される
//2.5e+6
console.log(test.toExponential(1));

//2.4827e+6
console.log(test.toExponential(4));


//有効桁数が少ない場合、指数表現に変換される
//2.483e+6
console.log(test.toPrecision(4));

//2482704.6
console.log(test.toPrecision(8));

//2482704.568
console.log(test.toPrecision(10));

prototypeの概念は今回の投稿内容とは別の領域になるので、別途詳しく掘り下げます。
簡単にいうと、javascriptの全てのオブジェクトにはprototypeを継承していて、最小のテンプレートという考え方ができます。

また、Numberのグローバル関数としては、次のようなものが定義されています。

Number.isFinite()
Number.isInteger()
Number.isNaN()
Number.isSafeInteger()
Number.parseFloat()
Number.parseInt()

型変換の際に使う関数としては、parseIntとparseFloatになりますが、
parseIntは整数のみ解析できることに対し、
parseFloatは整数と浮動小数点数の両方を解析できます。

以下、簡単なサンプルを書いて試してみます。

var test = 2482704.5681;
console.log(parseInt(test));    //2482704

var test = "24827テスト";
console.log(parseInt(test));    //24827

var test = "24827テスト";
console.log(parseFloat(test));  //24827

var test = 248.4587;
console.log(parseInt(test));    //248

var test = -248.4587;
console.log(parseInt(test));    //-248

var test = 0xFF;
console.log(parseInt(test));    //255

var test = 0xff;
console.log(parseInt(test));    //255

var test = 0xFD;
console.log(parseInt(test));    //253

var test = "0.1";
console.log(parseInt(test));    //0

var test = "0.2";
console.log(parseInt(test));    //0

var test = ".2";
console.log(parseInt(test));    //NaN

var test = "abcd.2";
console.log(parseInt(test));    //NaN

var test = "abcd.3";
console.log(parseFloat(test));  //NaN

実行した結果、上記のようになります。
数値として解釈できない場合には、NaNという処理結果になります。

型変換時の比較について

Posted コメントするカテゴリー: javascript

概要

等値演算子で値が等しいかの判定が行われる時、型変換が実行されます。

例えば、下記のようなコードを書いて出力してみます。
(コメント部分は出力結果です)

//trueと出力
console.log(null == undefined);

//trueと出力
console.log("50" == 50);

//falseと出力
console.log(60 == false);

//trueと出力
console.log(0 == false);

//falseと出力
console.log("70" == false);

//trueと出力
console.log("0" == false);

上記の実行結果で、trueと返るコードがあります。

等値による比較を行っていますが、それぞれ左辺と右辺で異なる型を書いていますが、比較するタイミングで型の変換が行われ、それを基に結果(true/false)が出力されていることがわかります。

例えば「0 == false」の比較では、右辺のfalseが比較時に一度0として変換された後に処理されているのがわかります。

等値演算子と、同値演算子の比較

等値演算子「==」による比較は上記にようになりますが、同値演算子の場合はどうなるでしょうか。

試しに、上記の例の比較部分を全て同値演算子に変更したコードを書いてみます。

//falseと出力
console.log(null === undefined);

//falseと出力
console.log("50" === 50);

//falseと出力
console.log(60 === false);

//falseと出力
console.log(0 === false);

//falseと出力
console.log("70" === false);

//falseと出力
console.log("0" === false);

上記の結果、全てfalseとして判定されました。

同値演算子の場合は、動的に型変換が行われず、厳密に型が違う為にfalseを返す挙動になります。

javascriptでは、値の変換がおこる場合、演算子や文で必要とされる型への変換が動的に行われます。

グローバルオブジェクト

Posted コメントするカテゴリー: javascript

グローバルオブジェクトについて

概要

グローバルオブジェクトとは、javascriptが実行された時にどこからでも呼び出すことができるオブジェクト。
以下のものがあります。

グローバルオブジェクトの例

グローバルプロパティ
undefined
Infinity
NaN

グローバル関数
isNaN()
perseInt()

コンストラクタ関数
Date()
RegExp()
String()
Object()
Array()

グローバルオブジェクト
Math
JSON

生成のしかた

通常、webアプリケーションを作成する場合はブラウザベースでの開発になります。
ブラウザで実行される場合、Windowオブジェクトがグローバルオブジェクトとなります。

グローバルオブジェクトが生成される際、グローバル値が設定されます。

グローバル変数として宣言した変数はグローバルオブジェクトのプロパティとして解釈されます。
以下に例を書きます。

//グローバル変数を用意する
var test_global = 10;

//windowオブジェクトのプロパティとしてアクセス
console.log(window.test_global);

//出力を確認
//「10」と出力される

nullとundefined

Posted コメントするカテゴリー: javascript

nullとundefinedについて

javascriptの予約語である

null

は値が存在しないことを表す値です。

nullの実行について

次のようなコードを書いて実行してみた結果、
コンソールに出力しても当然、nullが返ります。

var test = null;
console.log(test);

これをtypeof演算子を通して出力してみます。

console.log(typeof(test));

するとobjectという出力結果になります。

undefinedの実行について

このnullとは対照的にundefinedという予約語もあります。

意味としては「値が存在しない」というnullと同じですが、初期化されていない変数の値、オブジェクトのプロパティが存在しない、配列の要素が存在しない場合の、未定義の値を指すときを表します。

nullは予約語ですが、undefinedは予約語ではないです。

undefinedに対してtypeof演算子を使ってみます。

console.log(typeof(undefined));

実行するとそのままundefinedが出力されます。

また、一度変数に入れて実行すると、下記の例では同様にundefinedが出力されます。

var test2 = undefined;
console.log(test2);
console.log(typeof(test2));

nullとundefinedの比較

nullとundefinedを比較してみます。

以下のコードを書いて実行結果をみてみます。

var test_null = null;
var test_undefined = undefined;

if (test_null == test_undefined) {
	console.log("一致する");
} else {
	console.log("一致しない");
}

if (test_null === test_undefined) {
	console.log("一致する");
} else {
	console.log("一致しない");
}

上記の実行結果はともに「一致する」という出力結果になります。
一度変数に入れた両者の値として解釈されるので、等値(==)と同値(===)の判定条件でも同じになりました。
この記事を書いている段階では、変数に代入した後にどう解釈されているのか、もう少し深く理解する必要があります。

では、次のような直接的に書いて両者を比較する場合はどうなるか、試してみます。

if (null == undefined) {
	console.log("一致する");
} else {
	console.log("一致しない");
}

if (null === undefined) {
	console.log("一致する");
} else {
	console.log("一致しない");
}

この場合は、等値(==)の場合は「一致する」として、同値(===)の場合は「一致しない」という結果になりました。

nullとundefinedのオブジェクトについて

nullをtypeof演算子でみるとobjectという出力結果になります。
objectという結果になりますが、nullにはプロパティやメソッドもありません。

次のようなコードを書いて実行してみました。

//何も表示されない
null

//存在しないメソッドを呼ぶ
null.test();

結果、nullに対して存在しないメソッドを呼んでも

TypeError: null has no properties

という出力結果になります。

ここでは存在しないメソッドを呼びましたが、そもそもnullに対してはメソッドを追加することができない為、どのような場合でもTypeErrorになります。

論理値

Posted コメントするカテゴリー: javascript

概要

javascriptの論理値について、プログラムを書いて確かめます。

他のプログラム言語ではboolean型として、書くケースが多い論理値です。
真か偽か、trueかfalseか、といった2つのみの値を持つ変数になりますが、javascriptは特有のケースがあります。

変数の判定式を試す

論理値のサンプルを書いてみます。
以下のコードを書いて実行させてみます。

var test = 10;
if (test == 10) {
	console.log("一致する");
} else {
	console.log("一致しない");
}

実行すると「一致する」という結果になります。これは論理値の比較ではなく、変数の値の比較なので一致するという結果になります。

では、一度代入した変数そのものをif分で比較してみます。

var test = 10;
if (test) {
	console.log("一致する");
} else {
	console.log("一致しない");
}

上記の場合は「test」という部分がtrueかfalseかを判定する論理値になっている状態です。
結果は「一致する」という出力になります。

変数の判定式を試す(その2)

上記のように式全体の場合はわかりやすい例と言えます。

では、次のような例を書いて試してみます。

var test2 = null;
if (test2) {
	console.log("TRUE");
} else {
	console.log("FALSE");
}

この場合、test2という変数に対し、nullを代入しています。
その変数そのものをif分で判定すると、falseが返り、コンソールログ上の出力結果は「FALSE」となります。

このように、javascriptでは論理値でFALSEと判定される値があります。

必ずfalseになる値について

以下の値はfalseになります。

undefined
null
0
-0
NaN

配列の場合の判定結果

また、次のように配列を記述した場合

var testarray = [1, 2, 3, 4];

if (testarray) {
	console.log("TRUE");
} else {
	console.log("FALSE");
}

この場合の実行結果は「TRUE」になります。

また、論理値にはtoString()メソッドが使え、このメソッドを使った時はtrueかfalseがそのまま文字列として変数などに格納されます。

パターンマッチング

Posted コメントするカテゴリー: javascript

javascriptで文字列に対して正規表現を使ってパターンマッチングすることを試してみます。

概要

通常、javascriptではRegExpコンストラクタを使ってマッチングをします。
マッチする条件としては正規表現で書かれた内容を基にされます。
正規表現については、javascriptとは別カテゴリなので、別途詳しく掘り下げます。

正規表現の記載方法としてはperlのものと同様の書き方が有効なります。

パターンマッチングの例

javascriptでのパターンマッチングについて、一例を書きます。

//「パターン文字列」にマッチするかどうか
/パターン文字列/

//対象文字列の先頭が「パターン文字列」にマッチするかどうか
/^パターン文字列/

//0以外の数字にマッチするかどうか
/[1-9][0-9]/

//大文字小文字区別なしにjavascriptにマッチ
/\bjavascript\b/i

上記のようなパターンマッチが使えるので、次に実際にコードを書いてみます。

パターンマッチングの検証

実際に次のようなコードを書いた場合の、実行結果をコメント部分に書いています。

//対象文字列
var check_string = "abcdefghijkh1234";

上記の対象文字列(変数)に対して、マッチするパターンを決めます。

//文字列「abc」にマッチするパターン
var pattern = /abc/;

//先頭の文字列が「abc」にマッチするパターン
var pattern2 = /^abc/;

//文字列「h」にマッチするか
//(正規表現の最後の「/g」は文字列の最後まで検索を繰り返す
var pattern3 = /h/g;

対象文字列とマッチするパターンを組み合わせ、マッチングを実行します。

//マッチするかどうか検証

//trueが返る
console.log(pattern.test(check_string));

//trueが返る
console.log(pattern2.test(check_string));

//文字列「h」がcheck_stringの何番目になるか
console.log(check_string.search(pattern3));		//7が返る

//文字列「h」がヒット、検索結果は Array [ "h", "h" ] として返される
console.log(check_string.match(pattern3));

上記のコメント部分の結果が得られました。
パターンの記述方法や、マッチさせる方法はこの他にもあるので、実際にコーディングする場面が出てきたら追記します。

文字列操作

Posted コメントするカテゴリー: javascript

javascriptの文字列を操作する方法を試します。

文字列の連結は「+」で行います。
下記、例です。

var string_test = "test" + "1234";

上記の場合、変数string_testにはtest1234という文字列が代入されます。

文字列に対し、標準で装備されているメソッドを使うことができます。
下記、例です。(便宜上、console.log出力はしていません)

string_test.length();
string_test.charAt();
string_test.substring(2, 4);
string_test.slice(1, 3);

等のメソッドがあります。ここではメソッドについては一部抜粋しているだけなので、詳しくはリファレンスサイト等を確認するとよいです。

上記のメソッドについては、変数内の文字列に対して、メソッドを実行した結果を返す点に注意が必要です。
メソッドを実行した後でも変数内の文字列は変わらないです。

文字列リテラルとエスケープシーケンス

Posted コメントするカテゴリー: javascript

javascriptで文字列を扱う場合のまとめ

・単一引用符(シングルクォート)で囲む
・二重引用符(ダブルクォート)で囲む
・複数の行をまたいで記述可能
・複数行に分割する場合は「\」を使う
・文字列中に改行を含める場合は「\n」を使う
・単一引用符内の文字列にシングルクォートを含める場合は、エスケープ処理が必要。エスケープ処理は「\」を使う

また、javascriptはバックスラッシュについては、特別な意味を持ちます。
バックスラッシュの直後に特定の文字を記述すると、特定の制御コードを表します。

一例を挙げると「\n」は改行を表します(これは使用頻度が高いです)
また、以下にエスケープシーケンスの例を抜粋します。

//NULL文字
\0

//バックスペース
\b

//タブ
\t

//改行
\n

//垂直タブ
\v

//改頁
\f

//復帰
\r

//二重引用符
\"

//単一引用符
\'

//バックスラッシュ
\\

//2桁の16進数(XX)で指定するLatin-1文字
\xXX

//4桁の16進数(XXXX)で指定するUnicode文字
\uXXXX

上記の例がバックスラッシュの後に有効な制御コードになります。
この文字列以外の文字を指定すると、バックスラッシュが無視され、バックスラッシュの後の文字列が解釈されます。

日付と時刻

Posted コメントするカテゴリー: javascript

javascriptで日付と時刻を表すにはDate()コンストラクタを使います。

具体的には、下記のような書き方をします。(一例です)

//指定の日時
var date1 = new Date(2018, 5, 5);
var date2 = new Date(2018, 6, 5, 19, 15, 20);
console.log(date1); //Date 2018-06-04T15:00:00.000Z
console.log(date2); //Date 2018-07-05T10:15:20.000Z

//現在の日時
var date3 = new Date();
console.log(date3);

//各種、値の取得
console.log(date3.getFullYear());
console.log(date3.getMonth());
console.log(date3.getDate());
console.log(date3.getDay());
console.log(date3.getUTCHours());
console.log(date3.toString());
console.log(date3.toUTCString());
console.log(date3.toLocaleDateString());
console.log(date3.toLocaleTimeString());
console.log(date3.toISOString());

また、出力される値は型に注意して実装する必要があります。
見た目が数字なので全て数値型であるとは限らない為です。

上記の後半部分の実行結果はそれぞれ以下のように出力されます。

2018
6
5
4
8
Thu Jul 05 2018 17:54:46 GMT+0900
Thu, 05 Jul 2018 08:54:46 GMT
2018/7/5
17:54:46
2018-07-05T08:54:46.762Z

算術演算

Posted コメントするカテゴリー: javascript

javascriptの算術演算は次の演算があります

加算+
減算-
乗算*
除算/
剰余%

また、算術演算の他に、数学演算を行うMathというオブジェクトが標準で利用できます。

下記に一例を記載します。

console.log(Math.pow(3, 8)); //3の8乗
console.log(Math.round(0.7));
console.log(Math.ceil(0.7)); //整数に切り上げ
console.log(Math.floor(0.7)); //整数に切り捨て
console.log(Math.abs(-10)); //絶対値
console.log(Math.max(10, 15, 20)); //最大値
console.log(Math.min(10, 15, 20)); //最小値
console.log(Math.random()); //ランダムな数値を返す
console.log(Math.PI); //円周率
console.log(Math.E); //自然対数の底

/*
実行結果はそれぞれ以下のようになる
6561
1
1
0
10
20
10
0.9465591205735182
3.141592653589793
2.718281828459045
*/

javascriptでは、算術演算に以下のような特徴があります。

・オーバーフロー、アンダーフローが発生した場合にエラーにならない
・0で割った場合にもエラーにならない
・演算結果が最大値より大きくなった場合は無限大(Infinity)という値になる
・負の絶対値が最大を超えた場合、無限大負値になる(-Infinity)
・0を0で割ると、not-a-numberという「NaN」という出力になる
・無限大を無限大で割った場合もNaNになる
・InifinityとNaNはグローバル変数として定義される
・NaNの比較をすると、全ての値と等しくないという判定になる
・NaNとNaNを比較しても、等しくないという判定になる

プログラムを書いて実行した際に、コンソールログを確認してNaNやIntinityの表示が出てきた場合、上記のような算術演算の仕様を再確認することが重要になってきます。

数値を扱うプログラムが中心の場合は特に注意が必要になります。

浮動小数点リテラル

Posted コメントするカテゴリー: javascript

実数を記述する時には浮動小数点リテラルを使います。

浮動小数点リテラルでは、小数や指数も使用できます。

先頭が「整数部」、次に「小数点」、その後に「小数部」という形式になります。

以下、整数部+小数点+小数部の記述例です。

100.5
123.8
.005

次に、指数の記述例です。

7.2e5

これは7.2×10の5乗を表しています。

指数の書き方は「e」または「E」という形で記述します。
どちらでも同じ処理がされます。

そのe(またはE)の後に、プラス「+」かマイナス「-」を記述します。

例えば次のような場合もあります。

3.84e-15

この場合は3.84×10のマイナス15乗ということになります。

整数リテラル

Posted コメントするカテゴリー: javascript

javascriptのプログラム内で数値を表す場合は、10進整数で書きます。

10進整数の例

1
5
10
500

また、16進数(先頭が0xか0Xとして、その後に16進数)で指定することも可能です。

16進整数の例

コメント部分は10進数の値
0xf //15
0xff //255
0xC //12
0x7B //123
0x4D2 //1234
0x3039 //12345

16進数の詳しい説明はこちらのwiki(https://ja.wikipedia.org/wiki/%E5%8D%81%E5%85%AD%E9%80%B2%E6%B3%95)が参考になります

javascriptは8進数には対応していないので、10進数、16進数を使うようにします。(処理系によってはサポートしているが統一されていないのでNGと考えたほうがいいです)

数値

Posted コメントするカテゴリー: javascript

javascriptでの数値の扱いについてまとめ

  • 整数と浮動小数点は区別しない
  • 全ての数値を浮動小数点として扱う
  • 最大値は±1.7976931348623157x10の308乗
  • 小値は±5x10のマイナス324乗
  • 数値形式は-9007199254740992(-2の53乗)~9007199254740992(2の53乗)の整数
    (この範囲を超えると、精度が損なわれる)

 

Posted コメントするカテゴリー: javascript

javascriptの型について、簡単にまとめます。

型は大きく分けて2種類
基本型とオブジェクト型

基本型は、数値、文字列、論理値(真偽)、null、undefinedがある
オブジェクト型は、数値、文字列、論理値、null、undefined以外のjavascriptの値を示す

オブジェクトはプロパティの集合体
プロパティは名前と値の組み合わせを持つ

グローバルオブジェクトは特殊なオブジェクト
関数もオブジェクトとして扱う場合がある
コンストラクタの概念アリ。new演算子でオブジェクトを生成する際に初期化する時に使う関数

クラスはオブジェクト型の派生型にあたるもの
Arrayクラス、Functionクラス、Dateクラス、RegExpクラス、Errorクラスがある

javascriptにはガーベジコレクション機能がある
メモリの開放は自動的にされる

関数(メソッド)はオブジェクトに対して持つ
null、undefinedにはメソッドを呼び出すことはできない

値を変更できる型=オブジェクト(プロパティ)、配列(要素)
値を変更できない型=数値、文字列、論理値、null、undefined

変数には型の概念がない
どの型も代入可能
一度、代入した後に、違う型の変数を代入可能

変数はvarで宣言
構文スコープにより、関数外で宣言した変数はグローバル変数として、関数内と関数外からアクセス可能
関数内で宣言した変数は、関数スコープとなり関数内で利用可能

セミコロンについて

Posted コメントするカテゴリー: javascript

javascriptの行末はセミコロンを記述して、次のプログラムの先頭と明示的に分ける書き方が一般的です。

var a = 100;

ただし、セミコロンは必ず書かなければエラーになるという仕様ではありません。

例えば、下記のようなプログラムの場合、

var a = 100;
var b = 200;

console.log(a); //100
console.log(b); //200

変数aとbにはそれぞれ100と200が代入され、console.logに出力されますが、
次のように、変数aの最後のセミコロンを省いて書いたとしても、エラーにならずに実行されます。

セミコロンを省いた場合、改行が行末(プログラムの区切り)として処理されます。

var a = 100
var b = 200;

console.log(a); //100
console.log(b); //200

また、セミコロンを明示して、次のように1行に複数の命令を書くこともできます。

var a = 100; var b = 200;
console.log(a); //100
console.log(b); //200

ここまでで注意が必要な点は、改行が全て行末として解釈されるわけではないという点です。
次のような例は、処理のされ方がこれまでとは違います。

var a = 700
var b
c
=
800

console.log(a); //700
console.log(b); //undefined
console.log(c); //800

2行目、3行目で改行されていますが、変数bと変数cは別々のものとして解釈されています。
決して変数bcという単位で代入がされるわけではないです。

javascriptとして解釈されるには変数bが一旦、その行で終わったことになり、改めて変数cの暗黙的な定義がされた後に、値が代入されています。

このとき、変数cの行末は改行されていますが、セミコロンとしての解釈ではなく、次の2行の変数の代入までをひとつの命令として解釈しています。

改行がセミコロンとして解釈されない例があります。
下記の命令の場合は、処理に注意する必要があります。

//制御文の場合
return
break
continue

//インクリメント、デクリメント演算子
++
--

ポイントとなる点は、前者は制御文の直後に改行を行わないことと、
後者はインクリメントしたい変数と同じ行に演算子を書くことになります。

識別子

Posted コメントするカテゴリー: javascript

javascriptで変数や関数の名前を指定する際に使う名前を識別子といいます。

識別子は次のように書くルールがあります。

・先頭の文字はunicode文字、アンダーバー、$、とする
・数字は不可
・一般的にはASCII文字を使用する
・unicodeで表現できる文字も使用は可能(実際はあまり使われない)

リテラル

Posted コメントするカテゴリー: javascript

動的に型が決まるjavascriptは変数を宣言する時、型の指定がありません。

プログラムの実行時には、文字列数値真偽値nullundefined等の値の型が決定づけられます。

また、データ型はプリミティブ型とオブジェクトに分けられます。

プリミティブ型は基本型と呼ばれています。
オブジェクト型は参照型と呼ばれます。

上記のプリミティブ型は、値を指定すると変更できない性質をもち、
オブジェクト型は値を指定した後に、値自体を変更できる性質があります。

プログラム内に直接記述して表現する値をリテラルと呼びます。
実行時にもプログラムに書いた値がそのままの意味を持ちます。

下記に例を書きます。

10
1.0
"リテラル"
'リテラル'
true
false
null
undefined

上記は実行してもプログラム上の処理はなにもされません。

次のような例もあります

var a = 'test';
console.log(a);

この場合の変数aに代入した「test」もリテラル(文字列)で表現されたものと呼べます。
「test」と一度代入されたものは、プログラム実行中は変更しない(変数自体は書き換えられることがあっても)ので、プリミティブ型の値と呼ぶことができます。

また、オブジェクトリテラル、配列リテラル、関数リテラル、正規表現、などもあります。

{a:5, b:6}
[3, 4, 5, 6]

上記はそのまま記述するとエラーになります。

javascriptのエスケープシーケンス

Posted コメントするカテゴリー: javascript

javascriptは基本的にunicodeで記述します。
実行環境がunicodeをサポートしていない場合、エスケープシーケンスを使って表現することができます。

エスケープシーケンスは「\u」を先頭に下記、その後に4文字のASCII文字を記述して表します。

例えば

という文字を扱う場合は、エスケープシーケンス\uの後に「0151」という4文字の16進数を記述します。

\u0151

エスケープシーケンス後のunicode文字列の一覧については、こちらのwiki(https://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_0000-0FFF)に詳しくまとめられています。

特殊な文字列を取り扱う必要がある場合は、上記のサイトを参考にしてプログラムを書きます。

javascriptをHTMLタグ内に書く

Posted コメントするカテゴリー: javascript

前回の記事はHTMLソース内にjavascriptを書く方法と、外部ファイルにjavascriptを書く方法を試してみました。

また、HTMLソース内にjavascriptを書く方法は、HTMLソースのタグ内に書く方法もあります。

簡単なサンプルを書いてみました。

<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script>
//サンプル用関数(ボタン)
function alert_button()
{
	alert('test BUTTON!');
}

//サンプル用関数(リンク)
function alert_link()
{
	alert('test LINK !');
}
</script>

</head>
<body>

<button onclick="alert('test');">タグ内に直接書く</button>
<button onclick="alert_button();">タグ内から関数を呼ぶ</button>
<div onclick="alert_link();">文字に対してクリックイベントを付与</div>

</body>
</html>

ボタンが2個表示あり、HTMLソース内の button に対して、onclickイベントを付与しています。
このイベントはボタンを押したタイミングで発動されるもので、ユーザの動作に応じて命令が実行されます。
(他にもイベントの種類は多数あるので、別途まとめる予定です)

1つ目のボタンにでjavascriptのalert関数をそのまま呼び出していますが、2つ目のボタンには、HTMLのhead内に記述した独自の関数を呼び出しています。

また、ボタンの下の文字列に対しても、クリックした独自の関数を呼ぶようにイベントを付与しています。

どの方法でも動作には変わりはないですが、実装する場面で書き分けてプログラムします。

javascriptを書く場所

Posted コメントするカテゴリー: javascript

javascriptを書く場所は、クライアントサイドでプログラムを動作する場合は、ブラウザ内に直接記述するか、別ファイルとしてjavascriptを記述して読み込む方法があります。

HTMLソース内に直接記述する場合の例です。

<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>

HTMLソース内に直接記述する場合

<script type="text/javascript">
//ここに書いた命令がそのまま実行される
alert("クライアントサイドjs");
</script>

</body>
</html>

次の例はHTMLソース内から別ファイル(main.js)として記述したjsファイルを読み込んでいる例です。

<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="./main.js"></script>
</head>
<body>

HTMLソースから別ファイルを読み込む場合

</body>
</html>

どちらも実行されますが、比較的、外部ファイルとして読み込む場合が多く利用されています。
その場合は、読み込み順によってプログラムの実行結果に影響する場合があるので、注意します。

javascirptの条件分岐と、オブジェクトの使い方

Posted コメントするカテゴリー: javascript

javascriptの条件分岐を書きます。
他の言語と同様に条件分岐も一通りあります。

ただ、注意が必要なのは変数の型が明示的ではないので、条件の判定のされ方については、注意を払って書く必要があります。

var a = 3;

//値を条件により判別して分岐
if (a >= 4) {
	//3を超える場合
	console.log("3 over");
} else {
	//3以下の場合
	console.log("3 under");
}


//条件が真の場合、ループ処理し続ける
while (a < 6) {
	a++;
	console.log(a); //4 5 6 と出力
}


//条件が真の場合、ループ処理し続ける
for (var i = 0; i < 5; i++) {
	console.log(i); //1 2 3 4 と出力
}

また、オブジェクトを生成した後、オブジェクトに対してメソッドを追加する方法もあります。

その場合、インスタンスを生成した後にメソッドを追加しても、その生成したインスタンスからメソッドを呼ぶことができます。

下記、サンプルとして動作検証した結果です。

//オブジェクトを生成して、メソッドを追加

//コンストラクタ関数を定義する
function sampleobj(x, y) {
	this.x = x;
	this.y = y;
}

//インスタンスを生成する。newキーワードを使ってコンストラクタ関数を呼ぶ
var p = new sampleobj(3, 3);

//sampleobjオブジェクトのプロトタイプオブジェクトに関数を代入することで
//新規メソッドを定義する(例として、平方根を返すメソッドを追加)
sampleobj.prototype.r = function() {
	return Math.sqrt(
		this.x * this.x + this.y * this.y
	);
};

//sampleobjオブジェクトに対し、rというメソッドが使えるので、
//インスタンス経由でメソッドをコールする
console.log(p.r());

//最終的に「4.242640687119285」という出力がされる

javascriptの関数

Posted コメントするカテゴリー: javascript

javascriptの関数は、一般的なプログラム言語と同様の書き方はもちろん、関数そのものを変数に代入する書き方もあります。

また、配列や値を複数持つ配列をオブジェクトとみなし、オブジェクトに対しての関数をメソッドという名で呼び出して使うことができます。

メソッドについては、独自のメソッドを定義し、オブジェクトに付与して呼び出すこともできます。

下記の一連のプログラムは、実際に書いて動作させてみた結果です。

//関数の定義
function sample(a) {
	return a + 1;
}
//関数のコールと結果
console.log(sample(5)); //6



//関数の定義を変数に代入する方法
var sample_func = function(a) {
	return a + 2;
};
//関数のコールと結果
console.log(sample_func(7)); //9



//関数をオブジェクトと組み合わせる

//空配列を作成する
var a = [];

//配列に値を代入する
a.push(5, 6, 7);

//aをオブジェクトとしてみなすと、オブジェクトに対しての
//関数「メソッド」が使用できる

console.log(a); //Array[5, 6, 7]と表示される

a.reverse();

console.log(a); //Array[7, 6, 5]と表示される





//別々のオブジェクトを持つ配列を宣言する
var testarray2 = [
	{a:0, b:0},
	{a:2, b:2}
];

//配列に対し、独自メソッドを追加する
testarray2.dist = function() {

	var p1 = this[0]; //{a:0, b:0}の値のことを示す
	var p2 = this[1]; //{a:2, b:2}の値のことを示す
	
	//2つのオブジェクトの値(0:0)、(1:1)の平方根を求めて返す
	var a = p2.a - p1.a;
	var b = p2.b - p1.b;
	
	return Math.sqrt(a*a + b*b);
};

//別々のオブジェクトの平方根を求めた結果
console.log(testarray2.dist()); //2.8284271247461903