JavaScript/Global

出典: フリー教科書『ウィキブックス(Wikibooks)』
ナビゲーションに移動 検索に移動
XMLHttpRequest JavaScript
Global
Array

グローバルオブジェクト[編集]

グローバルオブジェクトは組み込みオブジェクトでブラウザ環境では window オブジェクトです。 例えば alert() メソッドの実体は、window.alert() です。 DOMが扱う対象の document も window.document です。 function f(){} とした場合のユーザーが定義した関数 f は window.f です。 このようにオブジェクトを指定しないで参照すると、グローバルオブジェクトのプロパティが参照されます。 ブラウザ環境以外では window はないので、 globalThis がグローバルオブジェクトになります。 ブラウザ環境でも globalThis がグローバルオブジェクトとして参照できます。

Global関数[編集]

グローバルオブジェクトのプロパティのうち typeof 値 が "function" なプロパティをグローバルなメソッドまたはグローバル関数(Global関数)と呼びます。

eval(x)[編集]

文字列を評価してその結果を返す。

eval関数の意味は、この一言で解説可能な単一の関数であるが、実際には様々な役割があり非常に重要なのでさらに解説を行う。

eval関数は文字列をJavaScriptとして評価して、その結果を返す。 そのため

var v=eval('100');  // 数字型の100をvに代入

などとすると、その結果が返ってくる。 このことから、何らかのユーザーの入力があったときに、その結果をJavaScriptで扱うことができる状態に変換可能である。 例えば、次のコードはHTMLで作成した、選択ボックスの結果を、evalでJavaScriptに変換した結果を逐次代入している。

<form id="enquete">
  <select id="yes-no">
    <option value="true" selected="selected">はい</option>
    <option value="false">いいえ</option>
  </select>
</form>
<script>
var ret = true;
document.getElementById('yes-no').onchange = function(e){
  ret = eval(this[this.selectedIndex].value);
}
</script>

(ただし入力紹介する結果が数値である場合は、後で紹介するparseIntやparseFloatの方が安全である)

さらに一歩推し進めて考えると、次の様に、計算式等もeval関数は処理をして、変数を呼び出す事も出来る。

document.write( eval('100+100'), '<br />' );  // 200を表示
var s='Hello';
eval('s +=",World!"');
document.write( s, '<br />' );  // Hello,World!を表示

ちなみにevalで呼び出せる変数の値は、グローバル変数(何処の関数のスコープにも属していない変数; 実体はグローバルオブジェクトのプロパティ)で無ければならないのを知っておくべきである。

ここまでを知っていると、eval関数はまた新たな使い道を考えることが出来る。 外部から取り出したテキストを評価して、データとして取り出す手法である。

var s = '{ "住所":"東京都", "年齢":28, "性別":"男" }';  // 仮に外部から取り出したとしたデータ
var o = eval('('+s+')');  // データを評価してJavaScriptデータに変換
document.write( o['年齢'] );

Webページ等で、外部と通信しながら、その結果を動的反映していくAjaxという手法では、この手法を使って主にデータの取り出しを行っている。 この様に、JavaScriptのデータ形式を文字列化(シリアライズ)して、データのフォーマットとして使われ出している。 この形式をJSON(JavaScript Object Notation)と言う。

実際には、コントロールされていない外部から文字列を受け取る場合には正しいJSONフォーマットではなく評価に失敗することがありうるため、エラーチェックのためにtry~catch文で囲うのがある。

var o;
try{
  o = eval('('+s+')');
} catch(e){
  // エラー処理
}

近年の流れとして、一部のJavaScript使用環境では、このJSON形式のデータを設定ファイルの保存形式等として使う流れも存在している。 その際の拡張子としては、txt や js 等も使われたが、json で標準化された(MIME-Typeは application/json)。

eval関数はJavaScriptでの入力結果を何の疑問も持たず評価するため強力なゆえ危険で、「エラー処理に飛ばなかった=安全」とは言えません。

JSONオブジェクト

JSONフォーマットの文字列をeval関数で評価することで不正なコードを実行してしまう危険を侵さぬよう、JSON オブジェクト がJavaScriptに加わり、JSON.parse() でJSON(であろう)文字列からJavaScriptのオブジェクトを、JSON.stringify() でJavaScriptのオブジェクトからJSONフォーマットの文字列をそれぞれ得ることが出来るよになりました。

数値処理関数[編集]

グローバルオブジェクトのメソッドは、いくつかの数値処理関数を標準で用意している。 これらは、Numberオブジェクトのメソッドの別名である場合と、機能的に近いものの挙動が違うものがあるので利用にあたっては注意が必要である。

parseInt(string , radix)[編集]

与えられた文字列を、先頭から解釈して整数に変換する。第2引数では、何進法とみなして変換を行うのかを指定する。 規格上、第2引数は省略した場合 0x で始まる16進法表記以外は10進法とみなして自動で変換を行っている。 Number.parseInt()の別名。

document.write( parseInt('10') );       // 10を表示
document.write( parseInt('10', 8 ) );   // 8を表示; 8進法として解釈、
document.write( parseInt('0x10') );     // 16を表示; 0xで始まる場合は16進数として解釈。
document.write( parseInt('0177') );     // 177を表示; 0で始まる場合も10進数として解釈。 ※ES5 0を前置する8進数表現は ES3 で非推奨、ES5で廃止
document.write( parseInt('0o77') );     // 0を表示; 0oで始まる場合も10進数として解釈。
document.write( parseInt('0b10') );     // 0を表示; 0bで始まる場合も10進数として解釈。
document.write( parseInt('ZERO') );     // 例外にならず NaN を表示; 1文字も数値として解釈できない。 
document.write( parseInt('3_14') );     // 3 を表示; _ を区切り文字とする記法には対応しない。
document.write( Number.parseInt === parseInt );     // Number.parseInt の別名。true を表示

parseFloat(string)[編集]

与えられた文字列を、JavaScriptのNumber型のオブジェクトに変換する。 Number.parseFloat() の別名。

document.write( parseFloat('10') );       // 10が表示
document.write( parseFloat('10.00') );    // 10が表示
document.write( parseFloat('0x10') );     // 16進数としては評価されない。最初の数字の「0」まで表示
document.write( parseFloat('10e+4') );    // 1000を表示
document.write( parseFloat('10E-3') );    // 0.01を表示
document.write( parseFloat('Infinity') ); // Infinityを表示
document.write( parseFloat('-Infinity') );// -Infinityを表示
document.write( parseFloat('NaN') );      // NaNを表示
document.write( parseFloat('Text') );     // NaNを表示
document.write( parseFloat('9n') );      // 99を表示
document.write( typeof parseFloat('9n') );// bigint でなく number を表示
document.write( typeof eval('9n') );      // bigint を表示
document.write( Number.parseFloat === parseFloat );     // Number.parseFloat の別名。true を表示

isNaN(number)[編集]

引数の値がNaN(Not-a-Number)であればtrueを、それ以外はfalseを表示。 Number.isNaN() とは動作が異なる。

document.write( isNaN(NaN) );	// trueを表示
document.write( isNaN(Math.sqrt(-1)) );	// trueを表示
document.write( isNaN(Math.sqrt( Infinity/Infinity )) );  // trueを表示
document.write( Number.isNaN === isNaN );  // falseを表示; Number.isNaN ではない
document.write( isNaN("NaN") );  // trueを表示; Stringからnumberに型変換され評価
document.write( Number.isNaN("NaN") );  // falseを表示; number でなければ false と即断

isFinite(number)[編集]

渡された値が有限数かどうかを判定する(Finiteは英語で「有限な」)。 正あるいは負の Infinity か NaN か undefined の時 false を返し、それ以外は true を表示。 Number.isFinite() とは動作が異なる。

document.write( isFinite(Infinity) );	// falseを表示
document.write( isFinite(100) );	    // trueを表示 
document.write( Number.isFinite === isFinite );// falseを表示 isFinite は Number.isFinite の別名ではない
document.write( isFinite(null) );	    // trueを表示; Stringからnumberに型変換され評価
document.write( Number.isFinite(null) );// falseを表示; number でなければ false と即断
document.write( isFinite("Infinity") );	// falseを表示; Stringからnumberに型変換され評価

URLエンコード関連関数[編集]

例えば次の様なリンクが存在したとしよう

http://ja.wikipedia.org/wiki/ネットスケープコミュニケーションズ

このリンクは日本語文字列を含んでいるため、実際にはURLとして利用できない。 そのため、これを英語と記号のASCII文字列の範囲の文字列で一度変換を行う必要がある。 これがURLエンコードと呼ばれる技術である。 (ただしこれは古い話で、現在はURLとして必要な文字列は多言語に対応している)

どの文字コードを基準とのするかは、実装によるがJavaScriptは文字列がUTF8と考えて処理を行う。

実際にURLエンコードを行う関数にはencodeURIとencodeURIComponentの2つがあるが、これらは微妙に実装が違う。 実際に先ほどのURLをそれぞれの関数で変換してみる。

document.write( 'http://ja.wikipedia.org/wiki/ネットスケープコミュニケーションズ' );
document.write( encodeURI('http://ja.wikipedia.org/wiki/ネットスケープコミュニケーションズ') );
document.write( encodeURIComponent('http://ja.wikipedia.org/wiki/ネットスケープコミュニケーションズ') );

実行結果は次の様に表示された。

http://ja.wikipedia.org/wiki/ネットスケープコミュニケーションズ
http://ja.wikipedia.org/wiki/%E3%83%8D%E3%83%83%E3%83%88%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BA
http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%8D%E3%83%83%E3%83%88%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BA 

日本語文字列以外にも、スラッシュ(/)等の一部の文字がencodeURIComponentでは変換されているのが分かる。 これらの変換の結果は次の様な法則が共通している。

  • 文字の中でも[0-9][a-z][A-Z]の文字列は変換されない
  • 日本語等の非ASCII文字列は基本的に変換される

なので、その外の記号文字列は変換結果の違うものなのでこれらを比較する。

無変換 ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { } ~
encodeURI ! %22 # $ %25 & ' ( ) * + , - . / : ; %3C = %3E ? @ %5B %5C %5D %5E _ %60 %7B %7C %7D ~
encodeURIComponent ! %22 %23 %24 %25 %26 ' ( ) * %2B %2C - . %2F %3A %3B %3C %3D %3E %3F %40 %5B %5C %5D %5E _ %60 %7B %7C %7D ~

少し図が見づらいかもしれないが、結果は一定の傾向があり、 encodeURIでは変換をされない文字は"#","/","&",":",";"等、URLで使用したり、CGIでパラメータを指定するときに特別な意味があるものである。

なので、これらの使い分けは次の様に分けるのが一つの基準となる。

  • URLを変換するときはencodeURI
  • データをcookieや外部のテキストとして出力するとき、CGIで入力された文字の安全な変換等はencodeURIComponent

このように変換した文字は、encodeURI、encodeURIComponentに対応するdecodeURI、decodeURIComponentという関数で元の文字列に戻すことができる。

encodeURI(uri)[編集]

URL(URI)として有効な範囲で、文字列をURLエンコードする。

// 変換して「JavaScript%E6%A8%99%E6%BA%96%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA」
encodeURI('JavaScript標準ライブラリ'); 

encodeURIComponent(uriComponent)[編集]

文字列をURLエンコードする。

// 変換して「JavaScript%E6%A8%99%E6%BA%96%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA」
encodeURIComponent('JavaScript標準ライブラリ');  

decodeURI(encodedURI)[編集]

encodeURIで行った変換を元に戻す。

// 「JavaScript標準ライブラリ」に戻す
encodeURI('JavaScript%E6%A8%99%E6%BA%96%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA'); 

decodeURIComponent(encodedURIComponent)[編集]

encodeURIComponentで行った変換を元に戻す

// 「JavaScript標準ライブラリ」に戻す
encodeURI('JavaScript%E6%A8%99%E6%BA%96%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA');