みこむらめもむらむらむら

なんかHTML5とかJS勉強とかやりながらめもを綴るブログ

【JavaScript】基本機能を提供する(Globalオブジェクト)

Globalオブジェクトとそのメンバ

Globalオブジェクトはグローバル変数
グローバル関数を管理するために
JavaScriptが自動的に生成する「便宜的な」オブジェクト
グローバル変数/グローバル関数とは
要は、関数配下に属さないトップレベルの変数/関数のこと
グローバル変数/関数は自分自身で定義することも可能だが
JavaScriptではいくつかデフォルトで提供している

特殊値

  • NaN
    • 数値でない(Not a Number)
  • Infinity
    • 無限大(∞)
  • undefined
    • 未定義値

チェック

  • isFinite(num)
    • 有限値かどうか(NaN、正負の無限大でない)
  • isNaN(num)
    • 数値でない(Not a Number)かどうか

変換

  • Boolean(val)
    • 真偽型に変換
  • Number(val)
    • 数値型に変換
  • String(val)
    • 文字列型に変換
  • parseFloat(str)
  • parseInt(str)
    • 文字列を整数値に変換

エンコード

  • escape(str)
    • 文字列をエスケープ処理
  • unescape(str)
    • エスケープ文字列をもとに戻す
  • encodeURI(str)
  • decodeURI(str)
    • 文字列をURIデコード
  • encodeURIConponent(str)
  • 文字列をエンコード
  • decodeURIConponent(str)
  • 文字列をデコード

解析

  • eval(exp)
    • 式/値を評価

これらのグローバル変数/関数は下記構文で参照できる

変数名
関数名(引数, ..)

数値へ明示的に変換する(parseFloat/parseInt/Number関数)

JavaScriptはデータ型に寛容な言語であり
その時々の文脈(前後の関数や演算子)によって
JavaScript側で適切なデータ型に自動変換してくれる
しかし、この自動変換が時として思わぬバグの温床になることがある
そのため、JavaScriptでは
データ型を明示的に変換するための方法を提供している
データ型を明確にした上で処理を行いたい場合
あるいは、変数の内容がそもそも曖昧である場合には
明示的にデータ型を変換することで
スクリプトの思わぬ挙動を未然に防ぐことができる

たとえば以下は与えられた値を数値に変換する
parseFloat/parseInt/Number関数の例である

var n = '123xxx';
document.writeln(Number(n));  //NaN
document.writeln(parseFloat(n));  //123
document.writeln(parseInt(n));  //123

変数nの「123xxx」のような文字列混在の数値が渡された場合
parseFloat/parseInt関数は「123」と解析できる部分だけを数値として取り込む
え、じゃあ「12xx12」みたいに混在したらどうなるの?
と思ってテストしたら「12」だけ返ってきた
あくまで先頭からの連続した数値のみらしい
「xxx123」だと「NaN」を返すのかーふむ

var d = new Date();
document.writeln(Number(d));  //1328161657227
document.writeln(parseFloat(d));  //NaN
document.writeln(parseInt(d));  //NaN

変数dのようにDateオブジェクトが渡された場合
parseFloat/parseInt関数はこれを解析できずにNaNを返すが
Number関数は「Dateオブジェクトを経過ミリ秒に換算した値」を数値として返す

var h = '0777';
document.writeln(Number(h));  //777
document.writeln(parseFloat(h));  //777
document.writeln(parseInt(h));  //511

var e = '1.01e+2';
document.writeln(Number(e));  //101
document.writeln(parseFloat(e));  //101
document.writeln(parseInt(e));  //1

さらに、変数hのように8進数の整数リテラル「0777」を解析した場合
parseInt関数だけはこれを8進数としてみなして「511」と返すが
その他の関数は「777」と返す
また、浮動小数点の指数表現「1.01e+2」を解析した場合
parseFloat/Number関数はこれを正しく解析するが
parseInt関数は末尾の文字列を「e+2」をサプレス(削除)し
さらに小数点以下を切り捨てた「1」を返す

ふむふむ目的に合わせて使い分けるの
気を付けましょうねってとこですね、はあく

グローバルオブジェクトが提供するグローバル関数Numberは
実は組み込みオブジェクトNumberでもある
そのため、下記のように書き換えても
Number関数と同様の結果が得られる

document.writeln(new Number(d));

データ型を明示で気に文字列型、論理型に変換したい場合も同様で、
それぞれString/Boolean関数を使用する
Number関数と同様、String/Boolean関数の実態は
String/Booleanオブジェクトであり
以下のいずれの書き方をしても意味は同じになる

var str = new String('123');
var str = String('123');

補足:算術演算子による文字列/数値への変換

文字列⇔数値の変換は算術演算子「+」「-」を利用することもできる

document.writeln(typeof(123 + ''));  //string
document.writeln(typeof('123' - 0));  //number

「+」演算子は与えられたオペランドのいずれかが文字列である場合
片方も同時に文字列に変換して連結するため
1行目は「string」が返ってくる
また、「-」演算子では与えられたオペランドのいずれかが数値である場合
もう片方を自動的に数値に変換したうえで減算する

クエリ情報をエスケープ処理する(encodeURI/encodeURIComponent関数)

たとえばGoogleやYahoo!のような検索エンジンを利用していると
以下のようなURLをみかけることがある

http://www.google.co.jp/search?q=%E3%81%BF%E3%81%93%E3%82%80%E3%82%89%E3%82%81%E3%82%82%E3%82%80%E3%82%89&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=ja&client=firefox-a

このようにURL末尾「~?」以降に「キー名=値&..」の形式で記述されているのは
サーバー上で動くアプリケーションへの問い合わせ必要なデータである
これをクエリ情報という、うんしってるー!
このクエリ情報は簡易である分渡せる情報にはいくつかの制限がある
たとえば、クエリ情報の区切り文字である「?」や「=」をはじめ
「%」、空白、マルチバイト文字などは使用できない
これらの文字がクエリ情報に含まれる可能性がある場合は
予め無害な文字列(「%xx」の形式)に変換しておく必要がある
このような変換処理をURIエンコードという
JavaScriptではencodeURI/encodeURIComponent関数で
URIエンコード処理を提供している

var str = '!"#$%&()+=*?@~_|;:,.';
document.writeln(encodeURI(str));
//!%22#$%25&()+=*?@~_%7C;:,.
document.writeln(encodeURIComponent(str));
//!%22%23%24%25%26()%2B%3D*%3F%40~_%7C%3B%3A%2C.

encodeURIComponent関数では
「#」「$」「+」「-」「/」「@」「;」「:」「,」なども
エンコードされている
それに対しencodeURI関数では変換されていない
また「!」「(」「)」「-」「*」「~」「_」などは
いずれの関数でも変換されない
encodeURI/encodeURIComponent関数でエンコードされた文字列は
decodeURI/decodeURIComponent関数を利用することで
元の文字列にデコードすることができる

encodeURI/encodeURIComponent関数によく似た関数として
escape関数があるがこちらは使用しているプラットフォームや
ブラウザ環境、文字コードなどによって得られる結果が異なるため
「下位互換性を維持したい」など特別な理由がない限り使用しない

動的に生成したスクリプトを実行する(eval関数)

eval関数は与えられた文字列を
JavaScriptのコードとして評価/実行する

var str = 'window.alert("eval 関数")';
eval(str);  //「eval 関数」と表示

これは文字列として渡されたwindow.alertメソッドを
eval関数で解析/実行する例である

このようにしてみると、eval関数は自在にJavaScriptのコードを引き渡し
実行することが可能になり柔軟にコーディングできるように見えるが
以下のような理由から、濫用は避けるべきである

  • 第3者による任意のスクリプトが自由に実行できてしまう可能性がある(セキュリティリスク)
  • 通常のコードを実行するよりも処理速度が遅い(パフォーマンスの劣化)

eval関数の利用はせいぜいJSONデータを解析する場合に留めるのが無難
その他の状況でeval関数を利用している場合
他の方法で置き換えられないか検討してみるべきである

了解いたしました‥