CommonJSはサーバーサイドJavaScriptを支える標準APIです。
クライアントサイドJavaScriptにはDOMという標準の拡張APIがありました。 しかし、サーバサイドJavaScriptやその他のJavaScript実行環境には このような標準APIがなく独自APIが多数存在し、ライブラリ利用者に大きな負担となっていました。
このため2009年頃からCommonJSという標準APIを定める活動が現れました。
そして、現在サーバサイドJavaScriptとして多く使われるNode.jsやJavaScriptを組み込んだアプリケーションはこのCommonJSに準拠したライブラリを備え、多数の開発者がCommonJS準拠のライブラリを使用しています。
このJavaScript実行環境OgOも、CommonJSに準拠したAPIを部分的に実装しています。今後 必要に応じてCommonJS APIを追加実装していく予定です。
| Buffer | バイナリデータ操作 |
| File System (fs) | ファイル操作 |
| Module | モジュール機能 |
| Path | Path操作 |
Buffer クラスは、バイナリデータを操作するためのクラスです。
| プロパティ | |
| length | バイナリデータのバイト数 |
| コンストラクタ | |
| Buffer | Bufferオブジェクトを作成 |
| メソッド関数 | |
| copy | バッファ間でコピー |
| fill | 指定された値でバッファを埋める |
| read{Type}
readUInt8,
readUInt16LE, readUInt16BE, readUInt32LE, readUInt32BE, readInt8, readInt16LE, readInt16BE, readInt32LE, readInt32BE |
バッファから整数を取り出す |
| toString | バッファの内容を文字列化 |
| write | 文字列をバイト化して書き込む |
| write{Type}
writeUInt8,
writeUInt16LE, writeUInt16BE, writeUInt32LE, writeUInt32BE, writeInt8, writeInt16LE, writeInt16BE, writeInt32LE, writeInt32BE |
バッファへ整数を書き込む |
| inspect | バッファの内容を文字列化 |
| クラスプロパティ | |
| INSPECT_MAX_BYTES | inspectメソッドで表示するバイト数 |
| クラス関数 | |
| byteLength | 文字列のエンコード(encoding)バイト列にサイズを得る |
| concat | バッファを結合 |
| isBuffer | Bufferオブジェクトかどうかを判定 |
var buffer;
buffer = new Buffer(8);
print( buffer.length ); // 8
buffer = new Buffer("あいう", "uft8");
print( buffer.length ); // 9
var buffer; buffer = new Buffer(8); print( buffer.inspect() ); // バッファの内容を表示不定 buffer = new Buffer([8,9,10]); print( buffer.inspect() ); // <Buffer 08 09 0a> buffer = new Buffer("あいう"); // buffer = new Buffer("あいう", "utf8"); print( buffer.inspect() ); // <Buffer e3 81 82 e3 81 84 e3 81 86> buffer = new Buffer("CAkKCwwN", "base64"); print( buffer.inspect() ); // <Buffer 08 09 0a 0b 0c 0d> buffer = new Buffer("08090a0b0c0d", "hex"); print( buffer.inspect() ); // <Buffer 08 09 0a 0b 0c 0d>
var buffer, bufferTarget; buffer = new Buffer([1,2,3,4,5,6,7,8]); bufferTarget = new Buffer(4); buffer.copy(bufferTarget); print( bufferTarget.inspect() ); // バッファの内容を表示 <Buffer 01 02 03 04> buffer.copy(buffer, 3); print( buffer.inspect() ); // <Buffer 01,02,03,01,02,03,04,05>
埋める値
埋める開始位置
埋める終了次位置
var buffer = new Buffer(8); buffer.fill(0); print( bufferTarget.inspect() ); // バッファの内容を表示 <Buffer 00 00 00 00 00 00 00 00> buffer.fill(0xff, 4); print( bufferTarget.inspect() ); // バッファの内容を表示 <Buffer 00 00 00 00 ff ff ff ff>
trueならoffsetの是非をチェックしない. false(省略時)ならチェックします.
| readUInt8 | --- | 1バイト 符号なし整数 |
| readUInt16LE | --- | 2バイト 符号なし整数(Little-Endian) |
| readUInt16GE | --- | 2バイト 符号なし整数(Big-Endian) |
| readUInt32LE | --- | 4バイト 符号なし整数(Little-Endian) |
| readUInt32GE | --- | 4バイト 符号なし整数(Big-Endian) |
| readInt8 | --- | 1バイト 符号あり整数 |
| readInt16LE | --- | 2バイト 符号あり整数(Little-Endian) |
| readInt16GE | --- | 2バイト 符号あり整数(Big-Endian) |
| readInt32LE | --- | 4バイト 符号あり整数(Little-Endian) |
| readInt32GE | --- | 4バイト 符号あり整数(Big-Endian) |
var buffer = new Buffer(6); buffer.writeUInt32LE(0xffffffff); buffer.writeUInt16LE(0x8000,4); print(buffer.readInt32LE(0)); // -1 print(buffer.readInt16LE(4)); // -32768
var buf = new Buffer([0x41, 0x42, 0x43, 0x44, 0x45]);
print( buf.toString('utf8', 2) ); // "CDE"
var buf = new Buffer([0x41, 0x42, 0x43, 0x44, 0x45]);
print( buf.toString() ); // "ABCDE"
var buf2 = new Buffer("あい");
buf.write(buf2, 2);
print( buf.toString() ); // "ABあ"
書き込む整数
バッファの先頭位置を指定する.
trueならoffsetの是非をチェックしない. false(省略時)ならチェックします.
| writeUInt8 | --- | 1バイト 符号なし整数 |
| writeUInt16LE | --- | 2バイト 符号なし整数(Little-Endian) |
| writeUInt16GE | --- | 2バイト 符号なし整数(Big-Endian) |
| writeUInt32LE | --- | 4バイト 符号なし整数(Little-Endian) |
| writeUInt32GE | --- | 4バイト 符号なし整数(Big-Endian) |
| writeInt8 | --- | 1バイト 符号あり整数 |
| writeInt16LE | --- | 2バイト 符号あり整数(Little-Endian) |
| writeInt16GE | --- | 2バイト 符号あり整数(Big-Endian) |
| writeInt32LE | --- | 4バイト 符号あり整数(Little-Endian) |
| writeInt32GE | --- | 4バイト 符号あり整数(Big-Endian) |
バッファの内容の表示バイト数を指定します。省略時はBuffer.INSPECT_MAX_BYTES.
print(Buffer.byteLength("あいう")); // 9
print("あいう".length); // 3
var buf1 = new Buffer([1,2,3]); var buf2 = new Buffer([0x10,0x20]); var buf = Buffer.concat( [buf1, buf2] ); print( buffer.inspect() ); // <Buffer 01 02 03 10 20>
調べたいオブジェクト.
var array = [1,2,3]; var buffer = new Buffer(array); print( Buffer.isBuffer(array) ); // false print( Buffer.isBuffer(buffer)); // true
File Systemは、ファイル操作を扱うモジュールです。
このモジュールを使うには、最初にrequire関数でモジュールをロードします。
var fs = require('fs'); print( fs.rename("test.dat", "text.txt) );
| rename, renameSync | ファイル名変更 |
| truncate, truncateSync | ファイルのサイズを変更 |
| unlink, unlinkSync | ファイルの削除 |
| exists, existsSync | パスがあるかチェック |
| chmod, chmodSync | ファイルのモードを変更 |
| readFile, readFileSync | ファイルからデータを読み出す |
| writeFile, writeFileSync | ファイルを作成し、データを書き込む |
| appendFile, appendFileSync | ファイルにデータを追記する |
| mkdir, mkdirSync | ディレクトリ作成 |
| rmdir, rmdirSync | ディレクトリの削除 |
| open, openSync | ファイルを開く |
| close, closeSync | ファイルを閉じる |
| write, writeSync | ファイルへデータを書く |
| read, readSync | ファイルからデータを読む |
var fs = require('fs');
try{
fs.rename("d:\\work\\t.dat", "d:\\work\\t.txt"); // t.datファイル名を t.txtに変更
}catch(e){
// ファイル名変更失敗
}
var fs = require('fs');
try{
fs.rename("d:\\work\\t.dat", 128); // t.datファイルのサイズを 128バイト変更
}catch(e){
// ファイルのイズ変更失敗
}
var fs = require('fs');
try{
fs.unlink("d:\\work\\t.dat");
}catch(e){
// ファイル削除を失敗
}
var fs = require('fs');
print( fs.exists("d:\\work\\t.dat"); //あればtrue, なければfalse
var fs = require('fs');
fs.chmod("d:\\work\\t.dat", 0666); //書き込みと読み取り(6 => 2|4)の権限をセットします
var fs = require('fs');
var txt = fs.readFile("d:\\work\\t.dat", 'utf8');
var fs = require('fs');
var buf = new Buffer([1,2,3,4,5]);
try{
fs.writeFile("d:\\work\\t.dat", "あいうえお', 'utf8');
fs.writeFile("d:\\work\\bin.dat", buf);
}catch(e){
//書き込み失敗
}
var fs = require('fs');
var buf = new Buffer([1,2,3,4,5]);
var buf2 = new Buffer([6,7,8,9,10]);
try{
fs.writeFile("d:\\work\\t.dat", "abcd", 'utf8');
fs.appendFile("d:\\work\\t.dat", "あいうえお', 'utf8');
fs.writeFile("d:\\work\\bin.dat", buf);
fs.appendFile("d:\\work\\bin.dat", buf2);
}catch(e){
//追記 失敗
}
var fs = require('fs');
try{
fs.mkdir("d:\\work\\A");
}catch(e){
//削除失敗
}
var fs = require('fs');
try{
fs.rmdir("d:\\work");
}catch(e){
//削除失敗
}
| 'r' | ファイルを読み込み専用でオープンします。 ファイルが存在しない場合は例外が発生します。 | |
| 'r+' | ファイルを読み書き両用でオープンします。 ファイルが存在しない場合は例外が発生します。 | |
| 'rs' | 'r'と同じ。 | |
| 'rs+' | 'r+'と同じ。 | |
| 'w' | ファイルを書き込み専用でオープンします。 ファイルは作成されるか (存在しない場合)、または長さ 0 に切り詰められます (存在する場合)。 | |
| 'wx' | 'w' と似ていますが、path が存在すると失敗します。 | |
| 'w+' | ファイルを読み書き両用でオープンします。 ファイルは作成されるか (存在しない場合)、または長さ 0 に切り詰められます (存在する場合)。 | |
| 'wx+' | 'w+' と似ていますが、path が存在すると失敗します。 | |
| 'a' | ファイルを追記用でオープンします。 ファイルが存在しない場合は作成されます。 | |
| 'ax' | 'a' と似ていますが、path が存在すると失敗します。 | |
| 'a+' | ファイルを読み込みおよび追記用でオープンします。 ファイルが存在しない場合は作成されます。 | |
| 'ax+' | 'a+' と似ていますが、path が存在すると失敗します。 |
var fs = require('fs');
var fd = -1;
var buffer, len;
try{
// write
fd = fs.open("mytext.data", "w", 0666);
fs.write(fd, "I like OgO.");
fs.close(fd);
// read
fd = fs.open("mytext.data", "r");
buffer = new Buffer(128);
len = fs.read(fd, buffer);
print(buffer.toString()); // I like OgO.
fs.close(fd);
}catch(e){
//失敗
}
var fs = require('fs');
var fd = -1;
var buffer;
try{
fd = fs.open("mydata.dat", "w", 0666);
buffer = new Buffer("あいう");
fs.write(fd, buffer);
fs.close(fd);
}catch(e){
//失敗
}
var fs = require('fs');
var fd = -1;
var buffer;
try{
fd = fs.open("mydata.dat", "r");
buffer = new Buffer(128);
fs.read(fd, buffer, 0, buffer.length);
print( buffer.toString() );
fs.close(fd);
}catch(e){
//失敗
}
CommonJSではモジュール機能を exports, moduleオブジェクトとrequire関数を使ってを実現します。
モジュールとして読み込まれる側のコードと、モジュールを読む側のコードをそれぞれ以下のように書きます。
■ モジュールとして読み込まれる側のコード smath.js
// smath.js
function add(x,y) {
return x + y;
}
function mul(x,y) {
return x * y;
}
exports.add = add; //add関数を他のモジュールから使えるようにexportします。
exports.mul = mul; //mull関数を ・・・
■ モジュールを読む側のコード sample.js
var smath = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード alert( smath.add(10, 20) ); // 30 alert( smath.mul(10, 20) ); // 200 //=別バージョン= var {add, mul} = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード alert( add(10, 20) ); // 30 alert( mul(10, 20) ); // 200
JavaScriptでは、複数のコードに同名のグローバル変数が定義されることを「変数の衝突」と呼んでいます。この「変数の衝突」がバグを起こす原因を多く作っています。
そこで exports変数,require関数を使ってモジュール化すれば、モジュールとして読み込まれる側のコードにある変数はすべてローカル変数となり「変数の衝突」を防げます。
そして モジュールの情報はmoduleオブジェクトにセットされています。
| exports | exportしたい変数や関数をプロパティにセットする |
| module | モジュール情報 |
| module.exports | exportしたい変数や関数をプロパティにセットする |
| module.filename | モジュールのフルパス名 |
| module.id | モジュールの識別子 |
| require関数 | ファイルモジュールをロード |
| require.main | メインモジュール |
| require.__reset__関数 | モジュールをリセット |
| __dirname | 現在実行されているスクリプトのディレクトリ |
| __filename | 現在実行されているスクリプトのフルパス名 |
exportsはモジュールとして読み込まれる側のコードにおいて、外部に公開したい関数やデータをexportsオブジェクトのプロパティにセットします。 各モジュールのexportsは異なるオブジェクトであり、このモジュールを読む側のコードのrequire関数の返値はこのexportsオブジェクトです。 exportsはmodule.exportsオブジェクトがセットされたモジュール内のローカル変数です。 例 ■ モジュールとして読み込まれる側のコード smath.js // smath.js function add(x,y) { return x + y; } function mul(x,y) { return x * y; } exports.add = add; //add関数を他のモジュールから使えるようにexportします。 exports.mul = mul; //mull関数を ・・・ ■ モジュールを読む側のコード sample.js var smath = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード alert( smath.add(10, 20) ); // 30 alert( smath.mul(10, 20) ); // 200 //=別バージョン= var {add, mul} = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード alert( add(10, 20) ); // 30 alert( mul(10, 20) ); // 200
moduleは実行中のモジュールの情報を含んだオブジェクトです。 各モジュールのmoduleは異なるオブジェクトであり、外部公開しない限り他のモジュールから参照できません。ただし、メイン(Scriptスタートモジュールの)moduleオブジェクトはrequire.mainで参照できます。 例 モジュールがメイン(Scriptスタート)モジュールかどうかの判定 if (module==require.main) { // このモジュールはメインモジュールである // ・・・ }
module.exportsはモジュールとして読み込まれる側のコードにおいて、外部に公開したい関数やデータをmodule.exportsオブジェクトのプロパティにセットします。 各モジュールのmodule.exportsは異なるオブジェクトであり、このモジュールを読む側のコードのrequire関数の返値はこのmodule.exportsオブジェクトです。 モジュール内のローカル変数 exportsは モジュール実行直前にmodule.exportsオブジェクトがセットされ、exportのコードを簡略にしています。 例 ■ モジュールとして読み込まれる側のコード smath.js // smath.js exportsオブジェクトを関数に変更する例 exports = module.exports = function() { alert("I am a smath-module."); } function add(x,y) { return x + y; } function mul(x,y) { return x * y; } module.exports.add = add; //add関数を他のモジュールから使えるようにexportします。 module.exports.mul = mul; //mull関数を ・・・ ■ モジュールを読む側のコード sample.js var smath = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード alert( smath.add(10, 20) ); // 30 alert( smath.mul(10, 20) ); // 200 smath(); // I am a smath-module.
module.filenameは実行中のモジュールのフルパス名です。
例
■ モジュールとして読み込まれる側でフルパス名を表示
// smath.js
function add(x,y) {
return x + y;
}
function mul(x,y) {
return x * y;
}
exports.add = add; //add関数を他のモジュールから使えるようにexportします。
exports.mul = mul; //mull関数を ・・・
alert(module.filename); // d:\work\smath.js
module.idは実行中のモジュールの識別子です。
現在の仕様では
file://モジュールのフルパス名
となっています。(将来変更される可能性あり)
例
■ モジュールとして読み込まれる側で識別子を表示
// smath.js
function add(x,y) {
return x + y;
}
function mul(x,y) {
return x * y;
}
exports.add = add; //add関数を他のモジュールから使えるようにexportします。
exports.mul = mul; //mull関数を ・・・
alert(module.id); // file://d:\work\smath.js
require関数を使ったモジュールロードは、「名前空間の衝突」を避けます。 さらに、ロードは最初の1回のみで次回からのrequire関数呼出はモジュールのロードされずシステムキャッシュに保存された exportsオブジェクトを返します。
例
■ モジュールを読む側のコード
var smath = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード
alert( smath.add(10, 20) ); // 30
alert( smath.mul(10, 20) ); // 200
//=別バージョン=
var {add, mul} = require('./smath'); // このコードと同じフォルダーにあるモジュールをロード
alert( add(10, 20) ); // 30
alert( mul(10, 20) ); // 200
//OgOの指定パス順序でモジュールをサーチ
var {WScript} = require("wsh");
var excel = WScript.CreateObject("Excel.Application");
excel.Visible = true;
require.mainはメイン(Scriptスタートモジュールの)moduleです。
requireは各モジュールの関数であることから、各モジュールはメインモジュールを知ることができます。
例
モジュールがメイン(Scriptスタート)モジュール)かどうかの判定
if (module==require.main) {
// このモジュールはスタートモジュールである
// ・・・
}
module.filenameと同じ内容です。
Pathは、ファイルパスを扱うモジュールです。
このモジュールを使うには、最初にrequire関数でモジュールをロードします。
var Path = require('path'); print( Path.basename("d:\\work\\test.dat") ); // test.dat
| 定数 | |
| sep | ファイルセパレータ |
| delimiter | 環境変数Path内の区切り |
| 関数 | |
| normalize | パス名を正規化 |
| join | 文字列を結合してパス名を作成 |
| resolve | 絶対パスを作成する |
| isAbsolute | 絶対パスかどうかを判定 |
| dirname | ディレクトリ名を取得 |
| basename | ファイル名を取得 |
| extname | 拡張子を取得 |
| parse | ファイルパスの各部分を取得 |
var Path = require('path');
'foo\\bar\\baz'.split(Path.sep); // ['foo', 'bar', 'baz']
var Path = require('path');
print( Path.normalize("d:\\work\\..\\t.dat") ); // d:\t.dat
print( Path.normalize("d:/work/../t.dat") ); // d:\t.dat
print( Path.normalize("..\\..\\t.dat") ); // ..\..\t.dat
var Path = require('path');
print( Path.join("work", "t.dat") ); // work\t.dat
print( Path.join("d:\\work", "..", "t.dat") ); // d:\t.dat
var Path = require('path');
print( Path.resolve("d:\\work", "test", "temp", "..", "t.dat") ); // d:\work\test\t.dat
print( Path.resolve("work", "test", "..", "t.dat") ); // d:\work\t.dat
var Path = require('path');
print( Path.isAbsolute("d:\\work\\test.dat") ); // true
print( Path.isAbsolute("work\\test.dat") ); // false
var Path = require('path');
print( Path.dirname("d:\\work\\test.dat") ); // d:\work
print( Path.dirname("work\\..\\test.dat") ); // work\..\test.dat
var Path = require('path');
print( Path.basename("d:\\work\\test.dat") ); // test.dat
print( Path.basename("work\\..\\test.dat") ); // test.dat
var Path = require('path');
print( Path.extname("d:\\work\\test.dat") ); // .dat
print( Path.extname("work\\..\\test") ); // 空文字列
var Path = require('path');
var ans = Path.parse("d:\\work\\test.dat");
print( ans.dir ); // d:\work
print( ans.root ); // d:\
print( ans.base ); // test.dat
print( ans.name ); // test
print( ans.ext ); // .dat