ログウインドウの右端にファイル名が付くけど、クラス名も書き出したい。
class xxxx{
static className = this.name;
...
}
は安定してクラス名が取得できるが、これは、staticなメソッドのみ参照可能で、インスタンス依存のメソッド用に
class xxxx{
className;
constructor() {
this.className = this.name;
...
}
...
}
か
class xxxx{
className;
constructor() {
this.className = this.constructor.name;
...
}
...
}
のいづれかが必要だった。どっちが常に正しいという訳では無いので、
static className = this.name;
className;
constructor() {
this.className = this.name ?? this.constructor.name;
...
}
~なぁあたりが良さそうだ。
??はあまり使わないけど、Null 合体演算子で、
「とりあえず【まともな値】を返す」場合に便利な演算子。
新しいパターンが増えたら
static className = this.name;
className;
constructor() {
this.className = this.name ?? this.constructor.name ?? {新しいパターン};
...
}
にすればいいだろう。
これで各メソッドに
メソッド名 (...) {
const methodName = '{メソッド名}';
console.debug(`${this.className}.${methodName}(...)`);
と書ける。
例外処理を発生してスタックを調べる事もできたけど、イマイチ感がある。
const getCurrentLineInfo = () => {
try {
throw new Error('getCurrentLineInfo Error');
} catch (ex) {
let stack = ex.stack.split('\n');
let target = stack[2];
// パターン1:at xxClass.yyMethod (https://{domain}/{path}/{filename}:{line}:{column})
// パターン2:at xxClass.yyMethod (file:///{drive}/{path}/{filename}:{line}:{column})
let match = target.match(/\s*at\s*([_a-zA-Z]+)[.]([_a-zA-Z]+)\s*([(])(.+?)([)])/);
// /\s*at\s*([_a-zA-Z]+)[.]([<>_a-zA-Z]+)\s*(?<=[(])(.+?)(?=[)])/ にすると失敗?
let className = match[1];
let methodName = match[2];
let url = match[4];
url = url.split(':');
let type = url.shift();
switch (type) {
case 'http':
case 'https':
var domain_fullpath = url.shift();
var [_, _, domain, ...fullPathName] = domain_fullpath.split('/');
fullPathName = '/' + fullPathName.join('/');
var row = url.shift();
var column = url.shift();
break;
case 'file':
var drive = url.shift();
var fullPathName = url.shift();
var row = url.shift();
var column = url.shift();
break;
}
let fileName = fullPathName.split('/').slice(-1)[0];
let fullPath = fullPathName.substring(0, fullPathName.length - fileName.length - 1);
var rc = {
type: type,
}
if (type == 'file') {
Object.assign(rc, {
drive: drive,
});
} else {
Object.assign(rc, {
domain: domain,
});
}
Object.assign(rc, {
fullPath: fullPath,
fileName: fileName,
className: className,
methodName: methodName,
row: row,
column: column,
});
}
return rc;
}
- 名前を調べる目的の割に長すぎる
- 関数を呼ぶ度に例外処理を起こすのは実行時間に響きそう
- chromeのスタック情報に依存したコードなので他ではエラりそう
サンプルでボタンを押すと表示する。
getCurrentLineInfo.jsのSampleClassクラスのexec()を呼び出した場合、
{
"type": "https",
"domain": "ssiscirine.iobb.net",
"fullPath": "/sample/stack",
"fileName": "getCurrentLineInfo.js",
"className": "SampleClass",
"methodName": "exec",
"row": "5",
"column": "12"
}
getCurrentLineInfo.jsのgetCurrentLineInfo()を直接呼び出した場合、
{
"type": "https",
"domain": "ssiscirine.iobb.net",
"fullPath": "/sample/stack",
"fileName": "stack.html",
"className": "HTMLButtonElement",
"methodName": "<anonymous>",
"row": "14",
"column": "43"
}
FireFoxではクラス名は無いけどメソッド名(関数名?)まで取れるのでサンプルの方は対応している。
HTMLのscriptやonclickからgetCurrentLineInfo()を直接呼び出した場合は行列位置は正しいので使えるけど、他は当てできないね。
それにしても
out.innerText = JSON.stringify(getCurrentLineInfo(),null," "); ※" "は全角1文字
と、インデントを指定すると、改行もしてくれるので読みやすい。※”\t”も良いらしい。