今となっては存在価値の無いハックだが、面白かったのでメモに残す。
TL;DR
アイデアの肝の部分のみ載せるとこうなる。(実際はこれだけだと動かない)
document.createElement("iframe").contentWindow.Object.prototype
完全版のコード
function getNoProtoObject() {
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
var obj = iframe.contentWindow.Object.prototype;
document.body.removeChild(iframe);
// for-inで列挙可能なプロパティを削除する
for (var name in obj) {
delete obj[name];
}
// for-inで列挙不可能な既知のプロパティを削除する
delete obj["constructor"];
delete obj["hasOwnProperty"];
delete obj["isPrototypeOf"];
delete obj["propertyIsEnumerable"];
delete obj["toLocaleString"];
delete obj["toString"];
delete obj["toSource"];
delete obj["valueOf"];
delete obj["watch"];
delete obj["unwatch"];
delete obj["__defineGetter__"];
delete obj["__defineSetter__"];
delete obj["__lookupGetter__"];
delete obj["__lookupSetter__"];
delete obj["__proto__"];
return obj;
}
説明
ECMAScript 3環境において[[Prototype]]内部プロパティがnullであるオブジェクトはObject.prototypeだけであるから、これをObject.create(null)相当のオブジェクトとして扱うほかない。
ところが、Object.prototypeは一つのページにただ一つしか存在しないオブジェクトであるから、Object.create(null)のように量産することができない。
この問題をいかに解決するかが課題となる。
上記の方法は、iframeでページ自体を新しく作ってしまって、そこからObject.prototypeを持ってくることで課題を解決している。
Object.prototypeには組み込みのプロパティがいくつか生えているので、最後の仕上げとしてそれらを削除すれば、まっさらなオブジェクトを得ることができる。
参考リンク
Was there a way to create an object without a prototype prior to ES5?
ところで
言わずもがな、このテクニックはもはや歴史的な意味合いしか持たない。
ECMAScript 3環境のブラウザには、IE 5.5〜8、Netscape 6、Firefox 3.0以前などがあるが、いずれも死んだブラウザである。
IE8ですら、日本標準時で2016年1月13日にサポートが打ち切られている。