Skip to content

Instantly share code, notes, and snippets.

@sounisi5011
Last active March 19, 2018 23:39
Show Gist options
  • Save sounisi5011/1c94e9ce21848e30678ab47ba03b4f54 to your computer and use it in GitHub Desktop.
Save sounisi5011/1c94e9ce21848e30678ab47ba03b4f54 to your computer and use it in GitHub Desktop.
入力した変数名のオブジェクトのプロトタイプを全て表示するデバッグ用ページ
<!DOCTYPE html>
<meta charset=utf-8>
<meta name=viewport content="width=device-width,initial-scale=1">
<meta name=format-detection content="telephone=no,email=no,address=no">
<title>入力した変数名のオブジェクトのプロトタイプを全て表示するデバッグ用ページ</title>
<link rel=stylesheet href=main.css>
<div id=main></div>
<h2>Gist</h2>
<a href=https://gist.github.com/sounisi5011/1c94e9ce21848e30678ab47ba03b4f54>https://gist.github.com/sounisi5011/1c94e9ce21848e30678ab47ba03b4f54</a>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es5,caniuse:console-basic&amp;flags=always,gated" crossorigin=anonymous></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hyperapp/1.2.0/hyperapp.js" integrity="sha256-nGvSTSqpX5gJdp7Jv5+4FCU1IbclUByINJqDQIbfwNc=" crossorigin=anonymous></script>
<script src=main.js></script>
pre {
overflow: auto;
}
.error {
color: red;
}
var MAX_SHOW_PROP_LENGTH = 6;
var MAX_STR_LENGTH = 200;
var MAX_SYMPLE_STR_LENGTH = 100;
var h = hyperapp.h;
var app = hyperapp.app;
/**
* 値を見やすい文字列表記に変換する
* @param {*} value 対象の値
* @param {boolean=} simple trueを指定した場合、表記を簡略化する
*/
var showValueData = function() {
/**
* @see https://stackoverflow.com/a/6969486/4907315
*/
var escapeRegExp = function(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};
var getObjectName = function(obj) {
var objStr = Object.prototype.toString.call(obj);
var match = /^\[object\s+([^\s\[\]]+)\s*\]$/i.exec(objStr);
return match ? match[1] : "[unknown object: " + objStr + "]";
};
var getDetails = function(value, simple) {
var varType = typeof value;
switch (varType) {
case "undefined":
return "undefined";
case "boolean":
case "number":
case "symbol":
return String(value);
case "string":
var maxLen = MAX_STR_LENGTH;
if (simple) {
maxLen = MAX_SYMPLE_STR_LENGTH;
value = value.replace(/\r\n?|\n/g, " ");
}
return (
'"' +
value.substr(0, maxLen) +
(maxLen < value.length ? "…" : "") +
'"'
);
case "function":
var name = getObjectName(value);
var funcStr = String(value)
.replace(/^(\s*)function(\s)/, "$1f$2");
var maxLen = MAX_STR_LENGTH;
if (simple) {
maxLen = MAX_SYMPLE_STR_LENGTH;
funcStr = funcStr.replace(/\s{2,}|\r\n?|\n/g, " ");
}
return (
funcStr.substr(0, maxLen) +
(maxLen < funcStr.length ? funcStr.replace(/(\}\s*)?$/, "…$&") : "")
);
case "object":
if (value === null) {
return "null";
} else {
var outputTextList = [];
if (simple) {
var name = getObjectName(value);
if (name !== "Object") {
return name + " {…}";
} else {
return "{…}";
}
} else {
for (var proto = value; proto; proto = Object.getPrototypeOf(proto)) {
var name = getObjectName(proto);
var propList = Object.getOwnPropertyNames(proto);
outputTextList.push(
name + " {" + (
propList
// .slice(0, MAX_SHOW_PROP_LENGTH)
.map(function(propName) {
try {
var valueStr = getDetails(proto[propName], true);
} catch(e) {
console.error(e);
return propName + ": (...)";
}
return propName + ": " + (
valueStr
.replace(new RegExp("^(f(?:unction)?\\s+)" + escapeRegExp(propName) + "(\\s*\\()"), "$1..$2")
);
})
// .concat(MAX_SHOW_PROP_LENGTH < propList.length ? ["…"] : [])
.join(", ")
) + "}"
);
}
return outputTextList.join("\n ");
}
}
break;
default:
return "unknown type [" + varType + "]";
}
};
return function(value, simple) {
console.groupCollapsed("showValueData()");
var ret = getDetails(value, simple);
console.groupEnd();
return ret;
};
}();
var state = {
value: undefined,
details: "",
error: undefined
};
var actions = {
showDetails: function(varName) {
return function(state, actions) {
try {
var value = Function("return " + varName + ";")();
var detailsText = showValueData(value);
return {
value: value,
details: detailsText,
error: undefined
};
} catch(e) {
return {
value: undefined,
details: "",
error: e
};
}
};
}
};
var view = function(state, actions) {
var err = state.error;
return h("p", {}, [
h("input", {
type: "text",
placeholder: "変数名を入力…"
}),
h("input", {
type: "button",
value: "表示",
onclick: function(e) {
return actions.showDetails(e.target.previousSibling.value);
}
}),
h("pre", err ? {class: "error"} : {}, (
err ?
(err.name + ": " + err.message) :
(state.details)
))
]);
};
app(state, actions, view, document.getElementById("main"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment