const command = process.argv[2]
argv[0] : javascriptのランタイム? ex. nodeの場合、’/usr/local/Cellar/node@14/14.18.3/bin/node’
argv[1] : 実行されたファイル(フルパス)
let x = [1, 2, 3]
let e = x.reduce((acc, cur) => acc + cur)
オブジェクトの場合は初期値を設定する
let x = [{count: 1, name: 'one'}, {count: 2, name: 'two'}, {count: 3, name: 'three'}]
let e = x.reduce((acc, cur) => acc + cur.count, 0)
let x = [1, 2, 3]
let e = x.reduce((pre, cur) => Math.max(pre,cur), 0)
let x = [1, 2, 3, 0]
x.sort((a, b) => a - b) //昇順
x.sort((a, b) => b - a) //降順
// オブジェクトの場合
let x = [{name: 'john', age: 44}, {name: 'paul', age: 40}]
x.sort((a, b) => a.age - b.age)
let arr = new Array(5)
arr.fill(true)
let arr = new Array(5)
arr.fill(true)
arr.every((x) => x)
Array.from({ length: 10 }, (_, index) => index);
Array.fromは第一引数に配列オブジェクトを受け取るのだが、{length: 10}とすることで擬似的に10個の長さのオブジェクトを表し、それを繰り返すことで配列が作成される
const newArray = [...originalArray])やslice(const newArray = originalArray.slice())によるコピーはシャローコピーと言って、配列の中がオブジェクトだとそのままの参照になる。中身も含めてコピーするのはディープコピーと言う。const deepCopy = JSON.parse(JSON.stringify(originalArray));
厳密にやるならloadashのライブラリを使うのがよいらしい
String.fromCharCode('1'.charCodeAt(0) + 0xFEE0)
String.fromCharCode('1'.charCodeAt(0) - 0xFEE0)
const i = 1.555
i.toFixed(2)
// -> "1.56"
文字列になる。
const result = 5.9;
const truncatedResult = Math.floor(result);
console.log(truncatedResult); // 出力: 5
delete演算子let obj = {name: 'john', age = 48}
delete obj.age
ただし、参照オブジェクトでは元のオブジェクトに影響を与える場合があるので、下のレストパターンで除くほうが安全。
let coffees = ['French Roast', 'Colombian', 'Kona'];
var car = { myCar: 'Saturn', getCar: carTypes('Honda'), special: sales };
オブジェクトリテラルとは、プロパティ名とそれに関連付けられたオブジェクトの値との 0 個以上の組が波括弧 ({}) で囲まれたもので作られたリストです。
スプレッド構文 (…) を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、0 個以上のキーと値の組 (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。 スプレッド構文は、オブジェクトや配列のすべての要素を何らかのリストに入れる必要がある場合に使用することができます。
↓これはECMAScript 2018 の新機能
let objClone = { ...obj }; // オブジェクトのすべてのキーと値の組を渡す
products = products.map( p => {
if (p.id === req.body.id) {
product = { ...p, ...req.body};
return product;
}
return p;
})
↑これの途中のスプレッドは{}でオブジェクトにしていて、pに含まれるキーと同じキーがreq.bodyにあるとreq.bodyの値(プロパティ)で書き換えられている
※ES2018より前はリストのスプレッドのみ. オブジェクトのスプレッドが2018から.
スプレッドはシャローコピー(浅いコピー)である。 第1階層はコピーされるが、値が配列やオブジェクトの場合は、元の値が共有されるので注意が必要。
const obj = { name: 'john', age: 40, sex: 'man' }
const copyobj = {...obj}
この場合のcopyobjはobjとは独立。
const obj = { group: 'beatles', menbar : [{ name : 'john'}, {name: 'paul'}]}
const copyobj = {...obj}
この場合のcopyobj.menbarは、objと共有されている
ES6?から、オブジェクトを再構成できる(縮小コピーともいうべきか)
product = {
name: 'kokuyo notebook',
price: 120,
stock: 2000,
salePrice: undefined
}
const {name, price, name:renameName, rating = 5, stock = 1800} = product
console.log(name, price) // -> kokuyo notebook 120
console.log(renameName) // -> kokuyo notebook これはプロパティのキー名を変更する例
console.log(rating) // -> 5 存在しないキーはデフォルト値を指定できる. デフォルトを指定しなかったらundefined
console.log(stock) // -> 2000 存在するキーはデフォルト指定は無視される
スプレッド構文を左辺に使うと、先に宣言したプロパティ以外のオブジェクトを生成できる。
const request = {
jobkind: 'typeA',
request: 'data',
editing: true,
anotherProp: 'value'
};
const { editing, ...rest } = request;
console.log(editing); // true
console.log(rest); // { jobkind: 'typeA', request: 'data', anotherProp: 'value' }
import './util.js'
// .jsはなしても可
import './util'
これでファイル全体は読み込めるが、util.jsの中の関数をimportしたスクリプトの中で使えないので、普通は次のように書く
import { add } from './util'
// 関数が複数ある場合は
import { add, square } from './util'
constの前にexportを書ける
export const square = (x) => x * x;
次の書き方をnamed exportという
const square = (x) => x * x;
export { square }
ファイルの中で一つはdefault exportにできる
const square = (x) => x * x;
export default square
//または export { square as default }
または
const square = (x) => x * x;
export { square as default }
または
export default square = (x) => x * x;
default exportはimport側では、同じ名前でなくていい. {}もいらない
import square2 from './util'
ES6からのclass propertyの書き方. ES6以前
class OldSyntax {
constructor() {
this.name = 'paul'
}
getGreeting() {
return `Hi, my name is ${this.name}`
}
}
const oldSyntax = new OldSyntax()
console.log(oldSyntax.getGreeting()); // ←これはOK
const getGreeting = oldSyntax.getGreeting
console.log(getGreeting()) // ←これはNG. `this`が効かないため
上記はclass propertyにして以下のように書く
class NewSyntax {
name = 'john'
getGreeting = () => { // ←アロー関数で書く=class propertyになる
return `Hi, my name is ${this.name}`
}
}
const newSyntax = new NewSyntax()
const getGreeting = newSyntax.getGreeting
console.log(getGreeting()) // ←OK
fsモジュールを使う
const fs = require("fs").promises;
→必ずプロミスを使う
const data = JSON.parse(await fs.readFile(file));
const data = fs.readFileSync(file));
const items = await fs.readdir(folderName, { withFileTypes: true});
const salesTotalsDir = path.join(__dirname, "salesTotals");
await fs.mkdir(salesTotalsDir);
存在しない親パスを含めると例外が発生するのでtry / catchをかけること
await fs.mkdir(path.join(__dirname, "newDir", "stores", "201", "newDir"), {
recursive: true
});
await fs.writeFile(path.join(salesTotalsDir, "totals.txt"), String());
await fs.writeFile(path.join(salesTotalsDir, "totals.txt"),
`${salseTotal}\r\n`, {flag: "a"});
const buf = fs.readFileSync('1-json.json')
const dataString = buf.toString()
const json = JSON.parse(dataString) // json 文字列を json オブジェクトに変換
json.name = 'Motoki'
json.age = 44
fs.writeFileSync('1-json.json', JSON.stringify(json)) //json オブジェクトを json 文字列に変換
stringifyはJSONオブジェクト”{}”を扱うが、リスト”[]”も扱える
const jsonStr = JSON.stringify({age: 48})
const jsonStr = JSON.stringify([1,2,3])
const http = require('http');
const PORT = 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('hello world');
});
server.listen(PORT, () => {
console.log(`listening on port ${PORT}`)
})
const express = require("express");
const app = express();
// ミドルウェア : http headersの"authorization"をチェックする
function isAuthorized(req, res, next) {
const auth = req.headers.authorization;
if (auth === 'secretpassword') {
next();
} else {
res.status(401);
res.send('Not permitted');
}
}
const port = 3000;
app.get("/", (req, res) => res.send("Hello World!"));
// ミドルウェア関数を引数に入れる
app.get("/users", isAuthorized, (req, res) => {
res.json([
{
id: 1,
name: "User Userson",
},
]);
});
app.get("/products", (req, res) => {
res.json([
{
id: 1,
name: "The Bluest Eye",
},
]);
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
const http = require("http");
http.get(
{
port: 3000,
hostname: "localhost",
path: "/users",
headers: { authorization : "secretpassword"},
},
(res) => {
console.log("connected");
res.on("data", (chunk) => {
console.log("chunk", "" + chunk);
});
res.on("end", () => {
console.log("No more data");
});
res.on("close", () => {
console.log("Closing connection");
});
}
);
通常、fetchで済ませる
以下の処理はCallbackで書いたものをPromiseで書き直したものである.
const doWorkCallback = (callback) => {
setTimeout(() => {
// callback('This is my error!', undefined) //←コチラを有効にすると呼び出し側のerrorが返る
callback(undefined, [1,4,7])
}, 2000)
}
doWorkCallback((error, result) => {
if (error) {
return console.log(error);
}
console.log(result)
})
const doWorkPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([7, 4, 1])
// reject('Things went wrong') //←コチラを有効にすると呼び出し側のcatchに入る
}, 2000);
})
doWorkPromise.then((result) => {
console.log('success', result);
}).catch((error) => {
console.log('error', error);
})
PromiseとはCallbackをより簡便に読みやすくするためのもの.
例えば上のCallbackの場合、doWorkCallbackのsetTimeoutの中のcallbackは何度も書くことができるのでバグの温床となる.
Promiseの場合、resolveまたはrejectで処理が終了するので、1度しか書くことができない.
また呼び出し側も.then、.catchとチェーンで書くことができるし、callbackで書いたときのif (error)の判定も不要になる.
Promiseはつなげることができる. →.thenを何度も書ける
const add = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b)
}, 2000)
})
}
↑こんなPromiseがあるとすると…
add(1, 2).then((sum) => {
console.log(sum);
add(sum, 2).then((sum2) => {
console.log(sum2);
}).catch((e) => {
console.log(e);
})
}).catch((e) => {
console.log(e);
})
↑このように入れ子にしなくても…
add(1, 2).then((sum) => {
console.log(sum);
return add(sum, 2)
}).then((sum2) => {
console.log(sum2);
}).catch((e) => {
console.log(e);
})
thenをつなげて書くことができる.
Promise chainをさらに発展させたのが async / await を使う書き方.
まずは基本形
const doWork = async () => {
}
console.log(doWork()); // return Promise { undefined }
↑空のasyncファンクションはPromiseを返す.
asyncファンクションは必ずPromiseを返す.
中身を入れたのがこれ↓
const doWork = async () => {
throw new Error('something wrong') //catchに返すならコチラ
return 'John'
}
doWork().then((result) => {
console.log('result', result);
}).catch((e) => {
console.log('e', e);
})
↑この書き方では特にPromiseと変わらない.
awaitを使うと↓こうなる.
const add = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (a < 0 || b < 0) {
reject('numbers must be non-negative')
}
resolve(a + b)
}, 2000)
})
}
const doWork = async () => {
const sum = await add(1, 99)
const sum2 = await add(sum, 50)
const sum3 = await add(sum2, 3)
return sum3
}
doWork().then((result) => {
console.log('result', result);
}).catch((e) => {
console.log('e', e);
})
awaitは必ずasyncの中に書くが、awaitを使うことによって、Promisechainのときの呼び出し側のthenが一回でよくなる.
thenでPromise chainで書くと変数のスコープも限られてしまうが、この書き方だとその必要もなくなる.