Console(consoleモジュールのConsoleコンストラクタ)

前回、consoleは"Consoleクラスのグローバルインスタンス"と言っていたけど、いろいろ調べていくと、consoleは"consoleモジュールのグローバルインスタンス"のほうが正しいのかなあっておもった・・・。

前回は、"consoleモジュールのグローバルインスタンス"について扱ったが、今回は"consoleモジュールのコンストラクタConsole"について扱う。

Console | Node.js v11.10.1 Documentation

コンストラクタに引数として、出力ストリームや、入力ストリーム、エラー出力ストリームを渡すことで、ファイルにログ出力などができる。
で、前回のグローバルインスタンス、今回のConsoleコンストラクタ含めて、いろいろな呼び出し方ができることがわかった。
まず、

前回のようなグローバルインスタンスで標準出力。

$ vi console1.js
$ node console1.js
AAA
$

こうなってました。
次に、

requireでconsoleモジュールの参照を取得し、varでcustomConsoleという変数に格納し、customConsole.logで出力。

$ vi console2.js
$ node console2.js
BBB
$

変わらない。
続いて、

customConsoleが、varによる変数から、constによる定数になっている。

$ vi console3.js
$ node console3.js
CCC
$

これも変わらない。
さて、ここから、

requireでconsoleモジュールの参照が取得できるわけだが、

分割代入 - JavaScript | MDN

constの次の"{Console}"、これは『分割代入』というJavaScriptの機能で、"その名前の要素を、その名前の変数に代入する"というもの。
consoleモジュールの中にはConsoleコンストラクタの参照があり、これをconstのConsoleに格納しているのである。

ここはfsモジュールで"output.log"への書き込みストリームを作成している。
('fs'モジュールについては後日・・・。)

Consoleコンストラクタの前にnewを付けて、オブジェクトを作成。このとき、outputStreamを渡すことで、outputStreamへの書き込みになる。
あとはlogで"DDD"を出力。

$ vi console4.js
$ node console4.js
$ ls
console1.js  console2.js  console3.js  console4.js  output.log
$ cat output.log
DDD
$

このように標準出力ではなく、"output.log"に"DDD"と書き込まれている。

さて、Consoleコンストラクタは、require('console')モジュールのConsole関数であるとも言える。

なので、それにnewを付けてオブジェクト生成をし、customConsoleに格納もできる。

$ ls
console1.js  console2.js  console3.js  console4.js  console5.js  output.log
$ vi console5.js
$ node -v
v10.15.0
$ node console5.js
/home/bg1/project/cloud/github.com/Sample/nodejs/Console/Console/src/Console/console5.js:5
customConsole.log("EEE"); // customConsole.logで'output2.log'に"EEE"を出力.
              ^

TypeError: Cannot read property 'log' of undefined
    at Object.<anonymous>
(/home/bg1/project/cloud/github.com/Sample/nodejs/Console/Console/src/Console/console5.js:5:15)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
output.log  output2.log
$ cat output2.log
$

ただし、これをv10.15.0でやったら、エラーが出てしまう。

$ sudo n 11.10.0
[sudo] bg1 のパスワード:
$ node -v
v11.10.0
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
output.log  output2.log
$ rm output2.log
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js  output.log
$ node console5.js
$ cat output2.log
EEE
$

そこで、nでv11.10.0に切り替えて、再度実行してみたら、今度は成功した。
(v10系のバグだろうか・・・。LTSなのに・・・。)

グローバルインスタンスのconsoleもrequire('console')と参照してるものは同じなので、

こういう風にもできる。

$ node -v
v10.15.0
$ vi console6.js
$ node console6.js
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
console6.js  output.log  output2.log  output3.log
$ cat output3.log
FFF
$

これはv10.15.0でも成功する。

Consoleは関数だから、別にnewで生成しなくても、require('console')の参照から関数として呼び出せる。(結局、newはいらない。)

$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
console6.js  console7.js  output.log  output2.log  output3.log
$ vi console7.js
$ node -v
v10.15.0
$ node console7.js
/home/bg1/project/cloud/github.com/Sample/nodejs/Console/Console/src/Console/console7.js:5
customConsole.log("GGG"); // customConsole.logで'output4.log'に"GGG"を出力.
              ^

TypeError: Cannot read property 'log' of undefined
    at Object.<anonymous>
(/home/bg1/project/cloud/github.com/Sample/nodejs/Console/Console/src/Console/console7.js:5:15)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
console6.js  console7.js  output.log  output2.log  output3.log
output4.log
$ cat output4.log
$ rm output4.log
$ sudo n 11.10.0
[sudo] bg1 のパスワード:
$ node -v
v11.10.0
$ node console7.js
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
console6.js  console7.js  output.log  output2.log  output3.log
output4.log
$ cat output4.log
GGG
$

これも、v10.15.0で失敗するが、v11.10.0だと成功。

グローバルインスタンスからの呼び出しも、

$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
console6.js  console7.js  console8.js  output.log  output2.log
output3.log  output4.log
$ vi console8.js
$ node console8.js
/home/bg1/project/cloud/github.com/Sample/nodejs/Console/Console/src/Console/console8.js:5
customConsole.log("HHH"); // customConsole.logで'output5.log'に"HHH"を出力.
              ^

TypeError: Cannot read property 'log' of undefined
    at Object.<anonymous>
(/home/bg1/project/cloud/github.com/Sample/nodejs/Console/Console/src/Console/console8.js:5:15)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)
$ ls
console1.js  console2.js  console3.js  console4.js  console5.js
console6.js  console7.js  console8.js  output.log  output2.log
output3.log  output4.log  output5.log
$ cat output5.log
$ rm output5.log
$ sudo n 11.10.0
$ node -v
v11.10.0
$ node console8.js
$ cat output5.log
HHH
$

これも、v10.15.0で失敗するが、v11.10.0だと成功。

とにかく、今回の一件で、いろんな呼び出し方があるということを知り、JavaScriptにはクラスなんて概念なんてないことを思い知らされ、バージョンによって出来たり出来なかったりなどなど、いろんなことを学んだ・・・。

Sample/nodejs/Console/Console/src/Console at master · bg1bgst333/Sample · GitHub

プロパティ

プロパティは、オブジェクトが持つさまざまな値のこと。他のオブジェクト指向言語でいう、メンバ変数、データメンバ、フィールドなどのこと。

JavaScript の基本文法

例えば、ブラウザ本体を表すNavigatorオブジェクトのappNameプロパティを表示するには、

こうすると、

appNameプロパティ
appNameプロパティ

このようにNavigatorオブジェクトのappNameプロパティが表示される。
にしても、"Netscape"って・・・。

Sample/js/property/property/src/property at master · bg1bgst333/Sample · GitHub

SetTextColor

SetTextColorは、TextOutなどでテキストを描画するときの文字色を設定する。

SetTextColor function | Microsoft Docs

WindowProcのWM_PAINTで、

TextOutの前に、SetTextColorで、16進数で色を指定した。
第1引数はhDCで、本来、第2引数にはCOLORREFで色を指定するが、実態はただの16進数、ただし、XBGR(ABGRって書いたけど正確にはXBGR)の順なので注意。
最後がffなので赤になるはず。

テキストが赤になった
テキストが赤になった

このようにテキストが赤になった。

Sample/winapi/SetTextColor/SetTextColor/src/SetTextColor at master · bg1bgst333/Sample · GitHub

basic_ostream::flush

flushは、バッファをフラッシュする。

basic_ostream::flush - cpprefjp C++日本語リファレンス

C言語のfflushのトピックのC++版である。
C言語では、'\n'など改行があるとフラッシュされるので、'\n'を出力せずにsleepさせた。
C++でも、std::endlなど改行があるとフラッシュされるので、std::endlを出力せずにsleepさせる。
で、そのsleepの前に、std::cout.flushでいったんフラッシュする。
こうすると、

実行時
実行時

実行直後に"str1"が出力されて、

5秒後
5秒後

5秒後に"str2"が出力される。

Sample/cpp/basic_ostream/flush/src/basic_ostream at master · bg1bgst333/Sample · GitHub

basic_ostream::write

writeは文字列(またはバイト列)を出力する。

basic_ostream::write - cpprefjp C++日本語リファレンス

stringオブジェクトのstrに"ABCDE"をセットし、writeの第1引数にはstr.c_str()でC言語形式で文字列を、第2引数にはstr.size()でサイズを渡す。

$ vi basic_ostream.cpp
$ g++ basic_ostream.cpp -o basic_ostream
$ ./basic_ostream
ABCDE$

改行はしないので、このように出力される。

Sample/cpp/basic_ostream/write/src/basic_ostream at master · bg1bgst333/Sample · GitHub

basic_string::c_str

C++のstring(basic_string)も時には、C言語の関数に渡したり、文字配列として扱う場合が度々あるだろう。
しかし、相手はC言語の仕様で作られている要素のため、そのまま渡すことはできない。

basic_string::c_str - cpprefjp C++日本語リファレンス

c_strは、stringオブジェクトの持つ文字列の先頭アドレスをC言語のconst char *で返してくれるメンバ関数
これを使えば、C言語の関数に渡したり、文字配列として扱ったりできる。

strの内容をstrcpyでbufにコピーしている。
strをそのまま渡せないので、str.c_str()として、文字配列の先頭ポインタを渡して、内容をコピーさせている。

$ g++ basic_string.cpp -o basic_string
$ ./basic_string
str = ABCDE
buf = ABCDE
$

bufにコピーできている。
C言語の関数、配列、と、C++のstringを同時に気軽に使える。

Sample/cpp/basic_string/c_str/src/basic_string at master · bg1bgst333/Sample · GitHub

basic_string::size

stringの正体は、

basic_string - cpprefjp C++日本語リファレンス

basic_string<char>であり、さまざまなメンバが定義されている。
sizeは、

basic_string::size - cpprefjp C++日本語リファレンス

文字列の長さを取得するメンバ関数

str1は後から"ABC"を代入、str2は初期化で"あいうえお"、str3は初期化で"かきくけこ"(stringにしているがbasic_string<char>と一緒。)をセットして、それぞれのサイズをsize()で取得している。

$ vi basic_string.cpp
$ g++ basic_string.cpp -o basic_string
$ ./basic_string
size1 = 3
size2 = 15
size3 = 15
$

utf-8環境なので、ここでは、英数字は1文字1バイト、日本語だと1文字3バイトになる。
文字数ではなく、文字列全体(NULL文字除く)にかかったサイズ(バイト数)を示しているのに注意。

Sample/cpp/basic_string/size/src/basic_string at master · bg1bgst333/Sample · GitHub