【JavaScript】正規表現で文字を自在に指定する(RegExpオブジェクト)③
マッチング情報を取得する
RegExpオブジェクトでは
execメソッドで最後にマッチした文字位置をはじめ
直近のマッチ情報を参照するためにいくつかのプロパティを公開している
- lastIndex
- 検索を開始する位置
- leftContext
- $`
- 最後のマッチ文字列の前の文字列
- rightContext
- $'
- 最後のマッチ文字列の後に続く文字列
- lastMatch
- $&
- 最後にマッチした文字列(Operaは未対応)
- lastParen
- &+
- 最後にマッチした()で囲まれたグループの文字列(Operaは未対応)
- lastParen
- パターンマッチした文字列を順に格納(最大9個)
全て静的プロパティ
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; while((result = p.exec(str)) != null){ document.writeln(p.lastIndex + ':' + result[0]); document.writeln('leftContext:' + RegExp.leftContext); document.writeln('rightContext:' + RegExp.rightContext); document.writeln('lastMatch:' + RegExp.lastMatch); document.writeln('lastParen:' + RegExp.lastParen); document.writeln('$1:' + RegExp.$1); document.writeln('$2:' + RegExp.$2); document.writeln('$3:' + RegExp.$3); document.writeln('<hr />'); }
36:http://micomura.hatenablog.jp/
leftContext:このブログは
rightContext:です。ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。
lastMatch:http://micomura.hatenablog.jp/
lastParen:/
$1:
$2:hatenablog.
$3:/
-------------------
79:HTTPS://twitter.com/micomura
leftContext:このブログはhttp://micomura.hatenablog.jp/です。ちなみにTwitterは
rightContext:だったりします。
lastMatch:HTTPS://twitter.com/micomura
lastParen:/micomura
$1:S
$2:twitter.
$3:/micomura
うむうむ
あとこんな風に書き換えられるそうな
RegExp.leftContext
RegExp['$`']
ほっほー
マッチングの成否を検証する
正規表現で「ただマッチしているかどうかを知りたい」場合にも
String.match/RegExp.execメソッドで
戻り値がnullであるかどうかを確認すれば
マッチングの成否を判定することが可能だが
testメソッドを利用すると
もっと簡単に検証することができる
testメソッドは与えられた文字列を検索し
その結果を真偽値(true/false)で返す
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str1 = 'このブログはhttp://micomura.hatenablog.jp/です。'; var str2 = 'ちなみにTwitterもやってたりします。'; document.writeln(p.test(str1)); //true document.writeln(p.test(str2)); //false
他にも指定された正規表現で
最初にマッチした文字位置を返すString.searchメソッドを
利用することもできる
searchメソッドはマッチ文字が存在しない場合に
戻り値として-1を返す
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str1 = 'このブログはhttp://micomura.hatenablog.jp/です。;' var str2 = 'ちなみにTwitterもやってたりします。'; document.writeln(str1.search(p)); //8 document.writeln(str1.search(p)); //-1
testメソッドわかりやすい結婚したい
正規表現で文字列を置き換える
String.replaceメソッドを利用すれば
正規表現でマッチした文字列を置換することができる
以下構文
置き換え対象の文字列.replace(正規表現オブジェクト, 置換後の文字列)
具体例
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; document.writeln(str.replace(p, '<a href="$1">$1</a>')); //
このブログは「http://micomura.hatenablog.jp/」です。
なるほどねー
置換後の文字列には「$1..$9」といった
特殊変数を埋め込める点に注意
これらはサブマッチ文字列を保存するための変数で
この例であれば以下のような値が
それぞれ$1~$4に格納されることになる
- $1
- $2
- undefined
- $3
- hatenablog.
- $4
- /
この例では正規表現全体を丸カッコで囲んでいる
これは特殊変数$1に
マッチング文字列全体をセットするための便宜的な措置である
あああーなるほど
これ丸カッコに気付いてなくて
特殊変数$1をdocument.writelnしても何も表示されなくて
(特殊変数$1、繰り上がった場合undefinedで運悪く空だから)
しばらく四苦八苦していた‥気を付けます‥
正規表現で文字列を分割する
正規表現で文字列を分割するにはString.splitメソッドを使用する
var p = /[\/\.\-]/gi; document.writeln('2012/02/01'.split(p)); //2012,02,01 document.writeln('2012.02.01'.split(p)); //2012,02,01 document.writeln('2012-02-01'.split(p)); //2012,02,01
上記は日付の文字を「/」「.」「-」で区切って
年月日に分解するコード
splitメソッドは戻り値として分割した結果を配列として返す
長かった正規表現も終わり!大丈夫か私
【JavaScript】正規表現で文字を自在に指定する(RegExpオブジェクト)②
はい次いきます
正規表現による検索の基本
RegExpオブジェクトの生成の次は
いよいよ文字列を検索する方法を見ていくことにする
以下は文字列からURL文字列を抽出するためのサンプル
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
おおーできた!
正規表現で検索するには、String.matchメソッドを利用する
(正確にはRegExp.execメソッドでも可能だがこちらは後述)
vは正規表現パターンにマッチした文字列を配列として返す
ここではforループで得られた配列の内容を順に出力している
正規表現のオプションでマッチング時の挙動を制御する
静企業玄以は「g」「i」「m」という3つのオプションがあり
これらを利用すれば正規表現検索の挙動を制御できる
さっきの例だとオプションを"gi"と設定しているので
「文字列全体」を「大文字/小文字区別なし」で検索している
それぞれのオプションを外してみると
どのように動作が変わるかみてみる
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/i; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
http://micomura.hatenablog.jp/
undefined
hatenablog.
/
"g"を外してグローバル検索を無効にしているため
最初に一致した文字列が見つかったところで検索を終了している
この場合、searchメソッドは
「最初に一致した文字列全体とサブマッチ文字列」を配列として返す
サブマッチ文字列とは正規表現パターンの中に
丸カッコで示された部分(サブマッチパターン)に
合致した部分文字列のこと
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/i;
ほーなるほど
この場合下記のようなサブマッチパターンに対して
それぞれ文字列が返ってきてるわけですね
- (s)
- undefined
- マッチしている部分がない場合はundefined(または空文字)が返ってくる
- ([\w-]+\.)
- hatenablog.
- 複数回マッチしている場合には最後にマッチしたもののみを保持
- (\/[\w- .\/?%&=]*)
- /
わかりました
それでは今度は"i"を外してみますよ
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/g; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
大文字/小文字の違いを無視しない(区別する)ように
設定しているため「http(s)://」は「HTTPS://」にはマッチしない
結果「http://micomura.hatenablog.jp/」だけが返ってくる
うむ、そりゃそうだ、わかりやすい
ややわかりにくいのがmパラメータ(マルチラインモード)
別のサンプルで一つ
var p = /^[0-9]{1,}/g; //文字列先頭にある1文字以上の数値を検索 var str = '101匹ワンちゃん\n7人の小人'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
101
マルチラインモードを無効にしている場合
正規表現パターン「^」は単に文字列の先頭を表すため
先頭の「101」にのみ合致する
これをマルチラインモードを有効にすると
var p = /^[0-9]{1,}/gm; //行頭にある1文字以上の数値を検索 var str = '101匹ワンちゃん\n7人の小人'; var result = str.match(p); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
101
7
マルチラインモードを有効にすると「^」は「行頭」を表す
結果改行コード「\n」直後にある「7」にもマッチする
なるほどなーふむふむ
また、これは「$」(文字列末尾)についても同様で
マルチラインモードを有効にした場合
「$」は「行末」を表す、はあく
また「/パターン /オプション」はそれ自体がリテラル表現のため
var result = str.match(/^[0-9]{1,}/gm);
このような記述もすることができる、ふむ
matchメソッドとexecメソッドの挙動の違い
正規表現の文字列検索をするには
- String.matchメソッド
- RegExp.execメソッド
を利用するが
これらのメソッドによって得られる結果は
条件によって異なる場合があるため注意が必要
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; var result = p.exec(str); for(var i = 0; i < result.length; i++){ document.writeln(result[i]); }
http://micomura.hatenablog.jp/
undefined
hatenablog.
/
execメソッドはグローバル検索(gオプション)が
有効か否かに関わらず
一度の実行で一つの結果しか返さない
代わりにマッチ文字列全体とサブマッチ文字列を
配列として返す
execメソッドでグローバル検索をした際と同じ結果を得るためには
RegExpオブジェクトの
- 最後にマッチした文字位置を記憶する機能
- 次回のexecメソッドを実行する際、前回のマッチ位置から検索を再開する
という特性を利用して
var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi; var str = 'このブログはhttp://micomura.hatenablog.jp/です。'; str += 'ちなみにTwitterはHTTPS://twitter.com/micomuraだったりします。'; while((result = p.exec(str)) != null){ document.writeln(result[0]); }
このように記述することで望んだ結果が得られるようになる
execメソッドは次の検索結果がない場合にnullを返す
検索を繰り返し
最終的に検索結果が返ってこなくなると
nullが返ってくるためwhile命令を脱出する
なるほどなーなるほどなー
【JavaScript】正規表現で文字を自在に指定する(RegExpオブジェクト)①
はい、やってまいりました正規表現
これ大事と云われていたのでがんばる
正規表現とは
たとえば下記文章から郵便番号だけ取り出したいとする
我が家の郵便番号は111-0500です。
引っ越す前は999-9763でした。
うむうむ
郵便番号自体はシンプルな文字列だが
番号だけを特定するには
- 先頭から順番に文字を検索する
- 数値が登場したら、その次とさらに次が数値であるか判定する
- さらにその次は『-』であるか
のように延々と判定していく必要がある
このような煩雑な手続きを踏むことなく
あいまいな文字列パターンを表現できる記法が
正規表現(Redular Expression)である
たとえば郵便番号は
「0~9の数値3桁」+「-」+「0~9の数値4桁」
というパターンで表せる
正規表現にすると
[0-9]{3}-[0-9]{4}
これを指定し、元の文字列と比較することで
任意の文字列の中から特定のパターンを持つ文字列を
検索することができる
ほっほーうべんり!記法は後述とのこと
JavaScriptで利用が可能な主な正規表現
基本
- ABC
- 「ABC」という文字列
- [ABC]
- A、B、Cのいずれか1文字
- [^ABC]
- A、B、C以外のいずれか1文字
- [A-Z]
- A~Zの間の1文字
- A|B|C
- A、B、Cのいずれか
量指定
- X*
- 0文字以上のX("fe*"は"f"、"fe"、"fee"などにマッチ)
- X?
- 0、または1文字のX("fe?"は"f"、"fe"にマッチ"fee"にはアンマッチ)
- X+
- 1文字以上のX("fe+"は"fe"、"fee"などにマッチ、"f"にはアンマッチ)
- X{n}
- Xとn回一致("[0-9]{3}"は3桁の数字)
- X{n,}
- Xとn回以上一致("[0-9]{3,}"は3桁以上の数字)
- X{m,n}
- Xとm~n回一致("[0-9]{3,5}"は3~5桁の数字)
位置指定
- ^
- 行の先頭に一致
- $
- 行の末尾に一致
文字セット
- .
- 任意の1文字に一致
- \w
- 大文字/小文字の英字、数字、アンダースコア(_)に一致("[A-Za-z0-9]"と同意)
- \W
- 文字以外に一致("[^\w]"と同意)
- \d
- 数字に一致("[0-9]"と同意)
- \D
- 数字に一致("[^0-9]"と同意)
- \n
- 改行(ラインフィード)に一致
- \r
- 復帰(キャリッジリターン)に一致
- \t
- タブ文字に一致
- \s
- 空白文字に一致("[\n\r\t\v\f]"と同意)
- \S
- 空白以外の文字に一致("[^\s]"と同意)
- \~
- 「~」で表される文字
うおー暗記系だーあーあー
たとえば上記をもとにURLを表す正規表現を読み解いてみると‥
http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
- http(s)?://
- 「(s)?」は「s」という文字が0または1回登場する、つまり「http://」か「https://」で始まることを表す
- ([\w-]+\.)+[\w-]+
- 英数字、アンダースコア、ハイフンで構成される文字列で、かつ途中にピリオドを含むことを表す
- (/[\w- ./?%&=]*)?
- 後続の文字列が英数字、アンダースコア、ハイフン、スラッシュ、ピリオド、その他特殊文字(?、%、&、=)で構成されうることを表す
お、おお‥(・∀・;)
わかった、何とかかろうじてわかった
これは慣れるしかなさそうだ‥
書いてある通りいろんな正規表現を見て
どういう意味かとかなんでそうなるかとかを考えないとだめだ‥
が、がんばります‥
RegExpオブジェクトを生成する方法
RegExpオブジェクトとは、JavaScriptで正規表現を解析し
文字列検索するための機能を提供する
生成する方法は大きく以下に分類できる
以下それぞれの構文
var 変数名 = new RegExp('正規表現', 'オプション'); //コンストラクタ var 変数名 = / 正規表現/ オプション ; //リテラル表現
正規表現リテラルでは、正規表現全体を
スラッシュ(/)で括らなければならない点に注意
「オプション」は正規表現の挙動を左右するパラメータで
以下のような値を指定できる
- g
- 文字列全体に対してマッチングするか(無指定の場合、1度マッチングした時点で処理を終了)
- i
- 大文字/小文字を区別するか
- m
- 複数行に対応するか(改行コードを行頭/行末と認識)
オプションを複数指定する場合には
"gi"のように並べて記述する
以上をふまえて
URL文字列にマッチングする
RegExpオブジェクトを生成してみると以下のようになる
var p = new RegExp('http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?', 'gi'); var p = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/gi;
記法そのものについても以下の2つの違いがある
RegExpオブジェクトの設定
諸パラメータコンストラクタで指定するほか
各種プロパティ/メソッドでも設定できる
(ただし、一部のパラメータは参照のみで設定は不可)
- sourse
- 正規パターンの取得
- 読み取り専用
- global
- グローバル検索("g"オプション)の有効/無効
- 読み取り専用
- ignoreCase
- 大文字/小文字を区別するか("i"オプション)
- 読み取り専用
- multiline
- マルチラインモード("m"オプション)
- 静的プロパティ
- input
- 検索対象の文字列
- 静的プロパティ
- compile(pattern)
- 正規表現パターンの設定
うむー、なんとなく、わかったような、わかってないような
とりあえず具体的にコード書かないとイメージしにくいなあ
次!
【JavaScript】日付/時刻データを操作する(Dateオブジェクト)
はいはいどんどん行きます!
Dateオブジェクトを生成する
Dateオブジェクトには他の文字列や配列などのように
リテラル表現は存在しない
オブジェクト生成には
必ずコンストラクタを経由する必要がある
はいはい出てきましたコンストラクタ
オブジェクトには、オブジェクトを初期化するために
オブジェクトと同名のメソッドが用意されている
この初期化メソッドのことをコンストラクタという
そうそうそうでした
この説明だけ読んでも訳が分からなかったのだけれど
なんかちょっとわかりそうな気がしてきたぞ
Dateオブジェクトのコンストラクタには以下4つがある
var d = new Date(); var d = new Date('2012/01/30'); var d = new Date(2012, 0, 30, 14, 29, 50, 500); var d = new Date(1217862000000);
デフォルトのDateオブジェクトを生成する
Dateオブジェクトは
デフォルトで生成された時点でのシステム日付をセットする
var d = new Date('2012/01/30');
日付文字列をもとにDateオブジェクトを生成する
ここでは「2012/01/30」という形式で日付を指定しているが
他にも「Mon Jan 30 2012 14:15:30」のような
英文形式で指定することもできる
var d = new Date(2012, 0, 30, 14, 29, 50, 500);
年月日/時分秒/ミリ秒の形式で指定したい場合は
この構文を利用する
この場合時分秒、ミリ秒は省略可能
月の指定が1~12でなく0~11で行う点に注意
var d = new Date(1217862000000);
1970/01/01 00:00:00からの
経過ミリ秒(タイムスタンプ値)で指定する方法
タイムスタンプを取得する方法は後述する
状況に応じてつかいわけるべし、はい!
Dateオブジェクトで利用可能なメンバ
ローカル(取得)
- getFullYear()
- 年(4桁)
- getMonth()
- 月(0~11)
- getDate()
- 日(1~31)
- getDay()
- 曜日(0:日曜~6:土曜日)
- getHours()
- 時(0~23)
- getMinutes()
- 分(0~59)
- getSeconds()
- 秒(0~59)
- getMilliseconds()
- ミリ秒(0~999)
- getTime()
- 1970/01/01 00:00:00からの経過ミリ秒
- getTimezoneOffset()
- 協定世界時との時差
var dat = new Date(); document.writeln(dat); //Mon Jan 30 2012 15:20:10 GMT+0900 document.writeln(dat.getFullYear()); //2012 document.writeln(dat.getMonth()); //0 document.writeln(dat.getDate()); //30 document.writeln(dat.getDay()); //1(月曜) document.writeln(dat.getHours()); //15 document.writeln(dat.getMinutes()); //20 document.writeln(dat.getSeconds()); //10 document.writeln(dat.getMilliseconds()); //587 document.writeln(dat.getTime()); //1327904410587 document.writeln(dat.getTimezoneOffset()); //-540
ローカル(設定)
- setFullYear(y)
- 年(4桁)
- setMonth(m)
- 月(0~11)
- setDate(d)
- 日(1~31)
- setHours(h)
- 時(0~23)
- setMinutes(m)
- 分(0~59)
- setSeconds(s)
- 秒(0~59)
- setMilliseconds(ms)
- ミリ秒(0~999)
- setTime(ts)
- 1970/01/01 00:00:00からの経過ミリ秒
var dat = new Date(); document.writeln(dat); //Mon Jan 30 2012 15:31:58 GMT+0900 dat.setFullYear(2010); dat.setMonth(4); dat.setDate(9); dat.setHours(8); dat.setMinutes(30); dat.setSeconds(25); dat.setMilliseconds(100); document.writeln(dat); //Sun May 09 2010 08:30:25 GMT+0900
協定時(取得)
- getUTCFullYear()
- 年(4桁)
- getUTCMonth()
- 月(0~11)
- geUTCtDate()
- 日(1~31)
- getUTCDay()
- 曜日(0:日曜~6:土曜日)
- getUTCHours()
- 時(0~23)
- getUTCMinutes()
- 分(0~59)
- getUTCSeconds()
- 秒(0~59)
- getUTCMilliseconds()
- ミリ秒(0~999)
var dat = new Date(); document.writeln(dat); //Mon Jan 30 2012 15:36:51 GMT+0900 document.writeln(dat.getUTCFullYear()); //2012 document.writeln(dat.getUTCMonth()); //0 document.writeln(dat.getUTCDate()); //30 document.writeln(dat.getUTCDay()); //1(月曜) document.writeln(dat.getUTCHours()); //6 document.writeln(dat.getUTCMinutes()); //36 document.writeln(dat.getUTCSeconds()); //51 document.writeln(dat.getUTCMilliseconds()); //129
協定時(設定)
- setUTCFullYear(y)
- 年(4桁)
- setUTCMonth(m)
- 月(0~11)
- setUTCDate(d)
- 日(1~31)
- setUTCHours(h)
- 時(0~23)
- setUTCMinutes(m)
- 分(0~59)
- setUTCSeconds(s)
- 秒(0~59)
- setUTCMilliseconds(ms)
- ミリ秒(0~999)
解析
- parse(dat)
- 日時文字列を解析し、1970/01/01 00:00:00からの経過ミリ秒を取得
- 静的メソッド
- UTC(y, m, d[,h [,mm [,s [,ms]]]])
- 日付情報をもとに1970/01/01 00:00:00からの経過ミリ秒を取得(協定時)
- 静的メソッド
document.writeln(Date.parse('1986/09/23')); //527785200000 document.writeln(Date.UTC(1986, 9, 23)); //530409600000
文字列変換
- toGMTSString()
- グリニッジ標準時を文字列として取得
- toUTCString()
- 世界協定時を文字列として取得
- toLocaleString()
- ローカル時を文字列として取得
- toDateString()
- 日付部分を文字列として取得
- toTimeString()
- 時刻部分を文字列として取得
- toLocaleDateString()
- 地域情報に従って、日付部分を文字列として取得
- toLocaleTimeString()
- 地域情報に従って、時刻部分を文字列として取得
- toString()
- 日時を文字列として取得
協定世界時とは国際的な協定で決められている公式時刻のこと
通常はグリニッジ標準時とほとんど同義だと思っておいて良い
(厳密には協定世界時は閏秒を加味している分だけ
グリニッジ標準時とは異なる)
日付/時刻データを加算/減算する
Dateオブジェクトでは、日付/時刻を
直接加算/減算するためのメソッドは用意されていない
このような計算を行うには
setXxxxxを利用して以下の手順で
個々の日付/時刻要素に加算/減算を行う必要がある
- getXxxxxメソッドで現在の日付/時刻要素を取得しておく
- 取得した値に加算/減算を行う
- さらにsetXxxxxメソッドで設定しなおす
以下具体例!
var dat = new Date(2010, 4, 15, 11, 40); document.writeln(dat.toLocaleString()); //2010年5月15日 11:40:00 dat.setMonth(dat.getMonth() + 3); //3ヶ月を加算 document.writeln(dat.toLocaleString()); //2010年8月15日 11:40:00 dat.setDate(dat.getDate() - 20); //20日を減算 document.writeln(dat.toLocaleString()); //2010年7月26日 11:40:00
ふむふむ
特定の要素に対する加算/減算の結果が
有効範囲を超えてしまっても
正しい日付に自動的に換算してくれる、べんりー!
この性質をつかって
その月の最終日を求めることもできる、ほう
var dat = new Date(2010, 4, 15, 11, 40); document.writeln(dat.toLocaleString()); //2010年5月15日 11:40:00 dat.setMonth(dat.getMonth() + 1); //来月の‥ dat.setDate(0); //0日目をセット document.writeln(dat.toLocaleString()); //2010年5月31日 11:40:00
なるほど‥「来月の0日目」はDateオブジェクトでは
「今月の最終日」になるわけですね、ふむふむ
日付/時刻の差分を求める
日付/時刻の差を求めるような処理に関しても
Dateオブジェクトは直接機能していないため
以下のようなコードを記述する必要がある
var dat1 = new Date(2010, 4, 15); //2010/05/15 var dat2 = new Date(2010, 5, 20); //2010/06/20 var diff = (dat2.getTime() - dat1.getTime()) / (1000 * 60 * 60 *24); document.writeln(diff + '日の差があります'); //36日の差があります
ここでは「2010/06/20」と「2010/05/15」との
日付差を計算している
日付差を求める場合にまず必要になるのが
2つの日付の経過ミリ秒である
経過ミリ秒を取得するのはgetTimeメソッドの役割
ここでは経過ミリ秒の差を求め
その値をもう一度日付に変換している
経過ミリ秒を日付に変換するのは以下公式できる
経過ミリ秒÷(1000ミリ秒×60秒×60分×24時間)
定型的な差分計算の例なので覚える必要あり
おぼえにくそうだ‥りょうかいしました‥
さてそろそろ疲れてきたぞ
【JavaScript】基本データを扱うためのオブジェクト②
Mathオブジェクト
指数計算や平方根、対数関数など
数学に関わる演算機能を提供する
全て静的プロパティ/メソッドである
また、Mathオブジェクトはnew演算子で
インスタンス化しようとすると実行エラーになる
基本
- abs(num)
- 絶対値
- max(num1, num2)
- num1、num2のうち、大きい方の値
- min()
- num1、num2のうち、小さい方の値
- pow(base, p)
- べき乗(値baseのp乗)
- random()
- 0~1未満の乱数
document.writeln(Math.abs(-15)); //15 document.writeln(Math.max(10, 15)); //15 document.writeln(Math.min(-15, 0)); //-15 document.writeln(Math.pow(2, 3)); //8(2の3乗) document.writeln(Math.random()); //0.18159612262285718(結果は実行ごとに異なります)
切り上げ/切り捨て
- ceil(num)
- 小数点以下の切り上げ(num以上の最小の整数)
- floor(num)
- 小数点以下の切り捨て(num以下の最大の整数)
- round(num)
- 四捨五入
document.writeln(Math.ceil(1.58)); //2 document.writeln(Math.floor(1.58)); //1 document.writeln(Math.round(1.58)); //2 document.writeln(Math.ceil(-1.58)); //-1 document.writeln(Math.floor(-1.58)); //-2 document.writeln(Math.round(-1.58)); //-2
平方根
document.writeln(Math.SQRT1_2); //0.7071067811865476 document.writeln(Math.SQRT2); //1.4142135623730951 document.writeln(Math.sqrt(3)); //1.7320508075688772
三角関数
- PI
- 円周率
- 読み取り専用
- cos(num)
- コサイン
- sin(num)
- サイン
- tan(num)
- acos(num)
- アークコサイン
- asin(num)
- アークサイン
- atan(num)
- アークタンジェント
- atan2(x, y)
- 2変数のアークタンジェント
document.writeln(Math.PI); //3.141592653589793 document.writeln(Math.cos(1)); //0.5403023058681398 document.writeln(Math.sin(1)); //0.8414709848078965 document.writeln(Math.tan(1)); //1.5574077246549023 document.writeln(Math.acos(1)); //0 document.writeln(Math.asin(1)); //1.5707963267948966 document.writeln(Math.atan(1)); //0.7853981633974483 document.writeln(Math.atan2(1, 1)); //0.7853981633974483 document.writeln(Math.cos(1)); //0.5403023058681398 document.writeln(Math.cos(1)); //0.5403023058681398
対数/指数関数
- E
- 自然対数の底
- 読み取り専用
- LN2
- 2の自然対数
- 読み取り専用
- LN10
- 10の自然対数
- 読み取り専用
- LOG2E
- 2を底としたeの対数
- 読み取り専用
- LOG10E
- 10を底としたeの対数
- 読み取り専用
- log(num)
- 自然対数
- exp(num)
- 指数関数(eの累乗)
document.writeln(Math.E); //2.718281828459045 document.writeln(Math.LN2); //0.6931471805599453 document.writeln(Math.LN10); //2.302585092994046 document.writeln(Math.LOG2E); //1.4426950408889634 document.writeln(Math.LOG10E); //0.4342944819032518 document.writeln(Math.log(Math.E)); //1 document.writeln(Math.exp(1)); //2.718281828459045
うむ、次!
Arrayオブジェクト
配列型の値を扱うためのオブジェクトで
配列に対する要素の追加/削除、結合、並び替えなどを
行うための機能を提供する
Arrayオブジェクトはリテラル表現を使って
var ary = ['佐藤', '田中', '鈴木'];
のように生成することもできるが
コンストラクタ経由で下記のように生成することもできる
var ary = new Array('佐藤', '田中', '鈴木'); //指定要素で配列を生成 var ary = new Array(); //空の配列を生成 var ary = new Array(10); //指定サイズ(インデックスは0~9)で空の配列を生成
ただしコンストラクタを利用した構文は
意味的に曖昧になりやすいという問題がある
var ary = new Array(10); //「長さが10の配列」なのか「10という要素を持つ配列」なのかわかりにくい var ary = new Array(-10); //「-10という要素を持つ配列」を生成するつもりが「長さが-10の配列」を生成しようとしてエラーになる
配列を生成するには極力
配列リテラルを利用すること
加工
- concat(ary)
- 指定配列を現在の配列に連結
- join(del)
- 配列内の要素を区切り文字delで連結
- slice(start [,end])
- start~end-1番目の要素を抜き出し
- splice(start, cnt [,rep [,..]])
- 配列内のstart+1~start+cnt+1番目の要素をrep,..で置き換え
追加/削除
- pop()
- 配列末尾の要素を取得し、削除
- push(data)
- 配列末尾に要素を追加
- shift()
- 配列先頭の要素を取得し、削除
- unshift(data1 [,data2 ,..])
- 配列先頭に指定要素を追加
並べ替え
- reverse()
- 逆順に並べ変え(反転)
- sort([fnc])
- 要素を昇順に並び変え
その他
- length
- 配列のサイズ
- toString()
- 「要素, 要素, ..」の形式で文字列に変換
var ary1 = ['Sanada', 'Kawata', 'Inoue', 'Mihara', 'Nogami']; var ary2 = ['Hoshino', 'Kamimura', 'Takemura', 'Okayama']; document.writeln(ary1.concat(ary2)); //Sanada,Kawata,Inoue,Mihara,Nogami,Hoshino,Kamimura,Takemura,Okayama document.writeln(ary1.join('/')); //Sanada/Kawata/Inoue/Mihara/Nogami document.writeln(ary1.slice(1)); //Kawata,Inoue,Mihara,Nogami document.writeln(ary1.slice(1, 3)); //Kawata,Inoue document.writeln(ary1.splice(0, 3, 'Inokoshi', 'Miura', 'Nagai')); //Sanada,Kawata,Inoue(置き換え対象の要素を取得) document.writeln(ary1); //Inokoshi,Miura,Nagai,Mihara,Nogami(置き換え後の配列) document.writeln(ary1.pop()); //Nogami(削除した要素) document.writeln(ary1); //Inokoshi,Miura,Nagai,Mihara(削除後の配列) document.writeln(ary1.push('Yamada')); //5(追加後の要素数) document.writeln(ary1); //Inokoshi,Miura,Nagai,Mihara,Yamada(追加後の配列) document.writeln(ary1.shift()); //Inokoshi(削除した要素) document.writeln(ary1); //Miura,Nagai,Mihara(削除後の配列) document.writeln(ary1.unshift('Komura', 'Ayase')); //6(追加後の要素数※だだしIEではundefined) document.writeln(ary1); //Komura,Ayase,Miura,Nagai,Mihara,Yamada(追加後の配列) document.writeln(ary1.reverse()); //Yamada,Mihara,Nagai,Miura,Ayase,Komura(反転後の配列) document.writeln(ary1); //Yamada,Mihara,Nagai,Miura,Ayase,Komura(反転後の配列) document.writeln(ary1.sort()); //Ayase,Komura,Mihara,Miura,Nagai,Yamada(ソート後の配列) document.writeln(ary1); //Ayase,Komura,Mihara,Miura,Nagai,Yamada(ソート後の配列) document.writeln(ary1.length); //6 document.writeln(ary1.toString()); //Ayase,Komura,Mihara,Miura,Nagai,Yamada
うむうむはあく!
下記、Arrayオブジェクトのメンバで注意すべきこと
多くのメソッドはもとの配列に影響を及ぼす
- Arrayオブジェクトのメソッドは、concatやslice、join、toStringといったメソッドを除くと、操作対象となるオリジナルの配列に影響を及ぼす
- 特に、reverse/sortなどのメソッドは、戻り値としても並べ替えの後の結果を返しますが、元の配列もソートされているので注意
配列の中身はtoStringメソッドで確認する
- toStringメソッドは配列内の要素をカンマで連結した文字列を返す
- 配列の中身を確認するには、toStringメソッドを使うと便利
- ちなみにdocument.writelnメソッドなど表示系のメソッドでは、配列オブジェクトを直接渡すことで内部的にtoStringメソッドが呼び出されるため、明示的にtoStringメソッドを呼び出す必要がない
- これはあれか、さっきの例の最後に記述した処理は「.toString()」なしでもいいということか
sortメソッドにはユーザ定義関数も指定可能
- sortメソッドでは、引数としてユーザ定義関数を指定し、デフォルトでは処理できないようなソート処理を独自に実装することも可能
- ただし、ユーザ定義関数は最低限、以下の規則にのっとっている必要がある
- 引数は2つ
- 第1引数が第2引数より小さい場合は負数、大きい場合は正数を返す
- たとえば、sortメソッドはデフォルトで数字も文字列としてソート処理するが、これを「数値としてソート処理したい」という場合には以下のように記述する
- ここでは(匿名)関数を使用しているため、コードの解説は割愛する
var ary = [5, 25, 10]; document.writeln(ary.sort()); //10,25,5(文字列としてソート) document.writeln(ary.sort( fonction(x, y){return x - y;} )); //5,10,25(数値としてソート)
うむ、最後にちょっとまとめ
基本データを扱うためのオブジェクト
- Stringオブジェクト
- 文字列型(string)の値を扱うためのラッパーオブジェクトで文字列の抽出や加工、検索などを行うための機能を提供する
- Numberオブジェクト
- 数値型(number)の値を扱うためのラッパーオブジェクトで数値の整形を行うための機能を提供するとともに無限大/無限小、数値型の最大値/最小値などの特別な値を表すための読み取り専用プロパティ(定数)を公開している
- Mathオブジェクト
- Arrayオブジェクト
- 配列型の値を扱うためのオブジェクトで配列に対する要素の追加/削除、結合、並び替えなどを行うための機能を提供する
それぞれ生成する場合は基本的にリテラル表現を使用する
うむうむ、はあく!
【JavaScript】基本データを扱うためのオブジェクト①
さ、前のわからなかった私が続きをやりますよ
Stringオブジェクト
文字列型(string)の値を扱うためのラッパーオブジェクトで
文字列の抽出や加工、検索などを行うための機能を提供する
var str = 'こんにちは';
new演算子で明示的に生成することもできるが
通常はリテラル表現を使って上記のような記述をする
ふむふむ
検索
- indexOf(substr [,start])
- 文字列前方(start+1文字目)から部分文字列substrを検索
- lastIndexOf(substr [,start])
- 文字列後方(start+1文字目)から部分文字列substrを検索
var str1 = 'にわにはにわにわとりがいる'; document.writeln(str1.indexOf('にわ')); //0(先頭から) document.writeln(str1.lastIndexOf('にわ')); //6(末尾から検索) document.writeln(str1.indexOf('にわ', 3)); //4(4文字目から右方向検索) document.writeln(str1.lastIndexOf('わ', 5)); //5(6文字目から左方向検索) document.writeln(str1.indexOf('ガーデン')); //-1(不一致)
部分文字列
- charAt(n)
- n+1番目の文字を抽出
- slice(start [,end])
- 文字列からstart+1~end文字目を抽出
- substring(start [,end])
- 文字列からstart+1~end文字目を抽出
- substr(start [,cnt])
- 文字列のstart+1文字目からcnt文字を抽出
- split(str [,limit])
- 文字列を分割文字列strで分割し、その結果を配列として取得(引数limitは最大分割数)
var str1 = 'にわにはにわにわとりがいる'; document.writeln(str1.charAt(11)); //い(12文字目を抽出) document.writeln(str1.slice(5, 8)); //わにわ(6~8文字目を抽出) document.writeln(str1.substring(5, 8)); //わにわ(6~8文字目を抽出) document.writeln(str1.substr(5, 6)); //わにわとりが(6文字目から6文字を抽出) document.writeln(str1.split('が')); //にわにはにわにわとり,いる document.writeln(str1.split('あ')); //にわにはにわにわとりがいる(対象文字列に含まれない文字列を分割文字列に指定) document.writeln(str1.split('わ', 3)); //に,にはに,に(3つに分割)
部分文字列を抽出する際の注意
- substring/sliceメソッド
- 開始位置~終了位置の範囲で抽出箇所を指定
- substrメソッド
- 開始位置からの文字数指定で抽出箇所を指定
substringメソッドとsliceメソッドの違い
- 引数start>引数endである場合
var str1 = 'みこむらめもむら'; document.writeln(str1.substring(8, 5)); //もむら(6~8文字目を抽出) document.writeln(str1.slice(8, 5)); //空文字
substringメソッドは引数startと引数endとの関係を入れ替えて
end+1~start-1文字目までを抽出するのに対し
sliceメソッドはこうした入れ替えは行わず、そのまま空文字を返す
うむ
- 引数start/endに負の数を指定した場合
substringメソッドは無条件に0とみなすが
sliceメソッドは「文字列末尾からの文字数」とみなす
var str1 = 'みこむらめもむら'; document.writeln(str1.substring(3, -2)); //みこむ(1~5文字目を抽出) document.writeln(str1.slice(3, -2)); //らめも(4~6文字目を抽出)
大文字⇔小文字
- toLowerCase()
- 小文字に変換
- toUpperCase()
- 大文字に変換
コード変換
- charCodeAt(n)
- n-1番目の文字をLatin-1コードに変換
- fromCharCode(c1, c2, ..)
- Latin-1コードc1、c2..を文字に変換
- 静的メソッド
文字装飾
- anchor(name)
- 文字列をアンカー化
- link(url)
- 文字列をリンク化
- sub()
- 下付き文字にする
- sup()
- 上付き文字にする
var str1 = 'みこむらめもむら'; document.writeln('TOP'.anchor(top)); //<a name="top">TOP</a> document.writeln(str1.link('http://micomura.hatenablog.jp/')); //<a href="http://micomura.hatenablog.jp/">みこむらめもむら</a> document.writeln('10'.sub()); //<sub>10</sub> document.writeln(str1.sup()); //<sup>みこむらめもむら</sup>
sub/supメソッドとかはあまり使わないとか
基本CSSで指定するからねー
その他
- concat(str)
- 文字列の後方に文字列strを連結
- length
- 文字列の長さを取得
var str1 = 'みこむらめもむら'; document.writeln(str1.concat('(・∀・)')); //<a name="top">TOP</a> document.writeln(str1.length); //8
正規表現に関しては後述があるそうです、うむ
たくさんあるなー‥次
Numberオブジェクト
数値型(number)の値を扱うためのラッパーオブジェクトで
数値の整形を行うための機能を提供するとともに
無限大/無限小、数値型の最大値/最小値などの特別な値を表すための
読み取り専用プロパティ(定数)を公開している
var num = 123;
Stringオブジェクトと同じように
new演算子で明示的に生成することもできるが
通常はリテラル表現を使って上記のような記述をする
プロパティ
- MAX_VALUE
- 利用できる最大値
- 静的プロパティ
- MIN_VALUE
- 利用可能な最小値(0に最も近い値)
- 静的プロパティ
- NaN
- 数値でない(Not a Number)
- 静的プロパティ
- NEGATIVE_INFINITY
- 負の無限大
- 静的プロパティ
- POSITIVE_INFINITY
- 正の無限大
- 静的プロパティ
POSITIVE_INFINITY/NEGATIVE_INFINITY、NaNは
いずれも特殊な数値(定数)を表す
POSITIVE_INFINITY/NEGATIVE_INFINITY(無限大)は
JavaScriptで表現可能な数値の範囲を超えた場合の
戻り値として利用される
NaN(Not a Number:数値以外)は
たとえば「0を0で除算した」など不正な演算が行われた場合に
数値として表現できない結果を表すために利用される
メソッド
- toString(rad)
- rad進数の値に変換(radは2~36)
- toExponential(dec)
- 指数形式に変換(decは小数点以下の桁数)
- toFixed(dec)
- 小数点第dec位で四捨五入
- toPrecision(dec)
- 指定桁数に変換(桁数が不足する場合は0で補う)
var num1 = 255; document.writeln(num1.toString(16)); //ff document.writeln(num1.toString(8)); //377 var num2 = 123.45678; document.writeln(num2.toExponential(2)); //1.23e+2 document.writeln(num2.toFixed(3)); //123.457 document.writeln(num2.toFixed(7)); //123.4567800 document.writeln(num2.toPrecision(10)); //123.4567800 document.writeln(num2.toPrecision(6)); //123.457
toFixedメソッドは小数点以下の桁数
toPrecisionメソッドは整数部の桁数も含めた全桁数
を指定する点に注意
NaNは、自分自身を含むすべての数値と等しくないため
以下のような比較式はfalseを返す
document.write(Number.NaN == Number.NaN)
NaN値を検出するにはisNaN関数を使用する必要がある
うむ、わかった
記事分けるよ
【JavaScript】オブジェクトとは
主役は「モノ」そのもの
JavaScriptのオブジェクトは
名前をキーにアクセスできる配列、要は連想配列である
と説明した
うむ、たしかにしている
【JavaScript】データ型のオブジェクトリテラル(object)のとこね
これはJavaScriptのオブジェクトを
実装的な視点からとらえるといった意味では正しいが
オブジェクトという概念そのもを説明するには不十分である
- オブジェクト
- 単に名前がついた入れ物の集合ではない
- オブジェクト自体が一つのモノであり、中に含まれる要素は、このモノの特性や動作を表すために存在する
- (連想配列ではなく)「オブジェクト」という言葉を使う場合には、主役は個々の要素ではなく、オブジェクト(モノ)そのものである
なんのことかなんとなくしかわからないのだが
例を見てなんとなくはあく
- 連想配列の場合
- 複数要素の集合体(個々の要素が主体)
配列data
- X0001
- 山田
- X0002
- 鈴木
- Z0099
- 佐藤
- U0108
- 田中
- オブジェクトの場合
- ひとつのモノを表現するために複数の属性情報を持つ(モノ全体が主体)
Memberオブジェクト
- name
- 山田
- sex
- 男
- birth
- 1983/10/20
- address
- 東京都‥
複数の属性情報って言い回しが
イメージしやすかったーなるほどー
プログラム上で扱う対象をオブジェクト(モノ)に見立てて
オブジェクトを中心としてコードを組み立てていく手法を
オブジェクト指向という
ほっほーなるほどです
オブジェクト=プロパティ+メソッド
オブジェクトはプロパティとメソッドとから構成される
ここでプロパティとメソッドキタ(゚∀゚)コレ
お久しぶりですね
プロパティとは
「オブジェクト(モノ)の状態や特性を表すための情報」のこと
対してメソッドは
「オブジェクト(モノ)を操作するための道具」
何言ってるかわからないので例を
オブジェクト:プログラムで扱う対象
例>>フォームを表すFormオブジェクト
- プロパティ:モノの状態や特性を表す情報
- フォームの名前
- フォームの送信先URL
- フォームに含まれる要素群
- etc..
- メソッド:モノを操作するための道具
- フォームを送信する
- フォームをクリアする
- フォームを無効化する
- etc..
プロパティ/メソッドという視点から見たとき
オブジェクトとは
「データを操作するためのさまざまな機能を持った」高機能な入れ物といえる
オブジェクトを利用するための準備(new演算子)
オブジェクト指向の世界では
後述するような例外を除いて
もともと用意されたオブジェクトを
直接利用することを認めていない
「自分自身の中でデータを保持できる」という性質を持っている
ふむ‥
たとえばオブジェクトに対して
アプリケーションが複数の箇所から
異なる目的で同一のプロパティを対象に
データを書き込んでしまったら
当然データは互いに衝突して
アプリケーションは正しく動作しない
そのためオリジナルのオブジェクトには手を加えず
「オリジナルを複製したコピー」を操作することで
データの競合を防ぐようになっている
このようにオブジェクトの複製を作ることをインスタンス化という
また、インスタンス化によってできる複製のことをインスタンスという
インスタンス化とは
「オブジェクトを扱うための『自分専用の領域』を確保する行為」
と言い換えられる
var 変数名 = new オブジェクト名([引数, ..])
オブジェクトには、オブジェクトを初期化するために
オブジェクトと同名のメソッドが用意されている
この初期化メソッドのことをコンストラクタという
オブジェクト名は、正確にいうと
コンストラクタ名である
‥‥‥(゚ロ゚;)ポカーン
生成されたインスタンスは変数に格納され
以降は、その変数をオブジェクトとして扱うことができる
インスタンスが格納された変数は
インスタンス変数、オブジェクト変数と呼ぶ場合もある
インスタンス変数からプロパティ/メソッドを呼び出すには
ドット構文を使って以下のように記述する
変数名.プロパティ名 [= 設定値]; 変数名.メソッド名([引数 [, ..]]);
‥‥‥(゚ロ゚;)ポカーン
どうしようちょっとよくわからない上に
これ以上の説明が載ってない‥
ちょっと先に進んでみる‥
静的プロパティ/静的メソッド
プロパティやメソッドによっては
例外的にインスタンスを生成せず利用できるものがある
このようなプロパティ/メソッドのことを静的プロパティ/静的メソッド
またはクラスプロパティ/クラスメソッドと呼ぶ
静的プロパティ/静的メソッドを呼び出すための一般的な構文
オブジェクト名.プロパティ名 [= 設定値]; オブジェクト名.メソッド名([引数 [, ..]]);
組み込みオブジェクトとは
JavaScriptでは多くのオブジェクトが公開されているが
その中でも最も基本的なものが
組み込みオブジェクト(Built-in Object:ビルトインオブジェクト)である
「組み込み」というのは
「JavaScriptにあらかじめ組み込まれた」という意味である
今後登場するブラウザオブジェクトが
特定の環境(ブラウザ上)でしか動作しないのに対し
組み込みオブジェクトは
JavaScriptが動作するすべての環境で利用することができる
また、JavaScriptでは自分でオブジェクトを定義することもできるが
これらの組み込みオブジェクトは
特別な宣言や定義を行うことなく利用できる
JavaScriptで利用可能な組み込みオブジェクト
- (Global)
- JavaScriptの基本機能にアクセスするための手段を提供
- Object
- 全てのおっぶジェクトにひな形となる機能を提供
- Array
- 配列を操作するための手段を提供
- String
- 文字列を操作するための手段を提供
- Boolean
- 真偽値を操作するための手段を提供
- Number
- 数値を操作するための手段を提供
- Function
- 関数を操作するための手段を提供
- Math
- 数値演算を実行するための手段を提供
- Date
- 日付を操作するための手段を提供
- RegExp
- 正規表現に関わる機能を提供
- Error
- エラー情報を管理
中でも下記はJavaScriptのデータ型に対応している
- Object
- Array
- String
- Boolean
- Number
- Function
オブジェクトを利用するには
インスタンス化という手続きを踏む必要があるが
JavaScriptではリテラルをそのまま
対応する組み込みオブジェクトとして利用できるため
インスタンス化をほとんど意識する必要がない
基本データ型でもnew演算子をつかって
var str = new String('こんにちは');
のように明示的にオブジェクトを生成することはできるが
ほとんどの場合冗長であるだけで
むしろ有害なことの方が多い
基本データ型をnew演算子を使ってインスタンス化するのは
原則として避けるべきである
JavaScriptの標準的なデータ型を扱う
組み込みオブジェクトの中でも
特に基本型の文字列、数値、論理値を扱うためのオブジェクトを
ラッパーオブジェクトという
ラッパーオブジェクトは
「単なる値にすぎない基本型のデータを包んで(ラップして)、
オブジェクトとしての機能を追加するするためのオブジェクト」
である
JavaScriptでは基本データ型と
オブジェクトとしての体裁を持つラッパーオブジェクトとを
自動的に相互変換するため
アプリケーション開発者がこれを意識する必要はない
ふむふむ‥なんか全体的に
‥‥‥(゚ロ゚;)ポカーン
なんだけれど概念的なところを聞いたら
ちょっとわかってきた、気がしている
気のせいか
とりあえず先に進むぞー