1行読んで書く
require('readline').createInterface({
input: process.stdin
}).on('line',function(line){
console.log(line)
process.exit(0)
})
1行ずつ、読んでは書く(上記と殆ど変わらないが)
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin
// output: process.stdout
});
rl.on('line', function(line) {
console.log(line);
});
ruby,python に比べて複雑な記述になるのは、 JavaScript言語の出自がCUIではないからだろう。
上記を短縮して書くこともできる(それでも長いが)
require('readline').createInterface({
input: process.stdin
// output: process.stdout
}).on('line', function(line) {
console.log(line);
});
ネイティブ JavaScriptには rubyのRangeに相当するものがないが、下のような裏技的な記法が知られている。
[...Array(10).keys()].forEach(i=>console.log(i))
回数を指定するだけならば keysを呼ばなくてもいい。
[...Array(10)].forEach(()=>console.log("hello"))
CやJavaと同様の記法も使える。
for(let i=1;i<10;i++) console.log(i)
for … in 、for … of の構文でもいい
for(let i in [...Array(10)]) console.log(i)
for(let i of [...Array(10)].keys()) console.log(i)
keys() で生成されているのは、数値ではなく文字列であることが、以下のような実験で確認できるだろう。(JavaScriptでは普段はあまり意識されずに使われているようだが)。
for(let i in [...Array(10)]) console.log(i+1)
for(let i of [...Array(10)].keys()) console.log(i+i)
上記の例で let は書かなくても動作するが、 ループ変数(ここでは i)の有効範囲を局所的にするために使うことが(最近は)推奨されている。
クライアント側JSとサーバ側JSで動作や使い方が違う領域だが、ここではサーバ側(node.js)を前提として書く。
非同期入出力と同期入出力の2つのアプローチがある。
const fs=require('fs') // この行は以下の例では省略する
fs.readFile('xxx.txt','utf8',(err,txt)=>{
console.log(txt)
})
console.log('=======')
// fsモジュールでは open, close は不要
終了を待つ読み書き関数を使う例:
const txt=fs.readFileSync('xxx.txt',{encoding:'utf8'})
console.log(txt)
エラー処理などについては省略する。実際に使う人はqiitaにある解説記事などを参照されたし。
ファイル名を指定して open し(ファイルディスクリプター fd がコールバック関数に渡される)その fdに対して readやwrite をする書き方も、fsモジュールが提供している。
結果に関して何もする必要がなければ同期出力でいい。
fs.writeFileSync('xxx.txt','この文字列が書き込まれます'')
fs.writeFile
がふさわしい(ここでは省略する)。1つのファイルに対しての書き込みが一回で完結しないようなプログラムの場合は、open して write、というアプローチの書き方が提供されている。
fs.open('xxx.txt','w',(err,fd)=>{
for(let i in [...Array(10)])
fs.writeSync(fd,`hello (${i})\r\n`)
fs.closeSync(fd)
})
' '
や " "
でなく
\
`で囲んだのは「テンプレートリテラル」生成(その中では
${ }`
の部分はブレース内の式の値を文字列にしたものに展開される)のため。const os=require('os')
// ...上記例の書き込みの行だけの変更例
fs.writeSync(fd,`hello(${i})${os.EOL}`)
JavaScriptには sleep関数はない。イベント駆動で非同期に動作するプログラムを作るための言語がその出自であるから。
疑似的にsleepを作り出す方法はいくつか提案されている(たとえばこういうページ)が、 ループとsleep的なものを組み合わせるのは JavaScript的ではないので、その代わりに setTimeoutと再帰を組み合わせる書き方を提示しておく。
(function(n) {
const x=arguments.callee
function y(){x(n-1)}
console.log(`${n}:${new Date().toLocaleTimeString()}`)
n>0 && setTimeout(y,1000)
})(10)
現在時刻は、例のようにDateオブジェクトのメソッドで生成するのが最も簡単。
この例では、外側の関数を無名関数にしている(名前つきの関数定義をしても構わないが名前空間を消費しない方針のときはこう書くことになるという例でもある)。
arguments.callee
という属性値を使っている。上記のプログラムの出力を(consoleではなく)ファイルに書き込むには、もう少し複雑な記述が必要になる。
const fs=require('fs'), os=require('os')
fs.open('xxx.txt','w',(err,fd)=>{
if(err)throw err;
(function(n,fd) {
const x=arguments.callee
function y(){x(n-1,fd)}
fs.writeSync(fd,`${n}:${new Date().toLocaleTimeString()}${os.EOL}`)
if(n>0)setTimeout(y,2000)
else{fs.closeSync(fd);console.log("ok")}
})(10,fd)
})