Object.setPrototypeOf を作る
https://mail.mozilla.org/pipermail/es-discuss/2013-March/029259.html で気付かされた。
Firefox なら Object.setPrototypeOf
を作ることができる。
Firefox、というよりも、SpiderMonkey なのだが、Object.prototype.__proto__
がgetter/setterで定義されている。
Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); /* { configurable: true, enumerable: false, get: function () { [native code] }, set: function () { [native code] } } */
Firefox 17 からは、上記のようになっている。このDescriptorからsetを取り出してあげれば、待望のObject.setPrototypeOf
を作れる。
(function() { var protoDesc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); if (typeof protoDesc.set === "function") { Object.defineProperty(Object, "setPrototypeOf", { value: Function.prototype.call.bind(protoDesc.set), configurable: true, writable: true }); delete Object.prototype.__proto__; } }());
Object.create(null)
で作ったprototypeが無いオブジェクトにも安心してプロトタイプ設定が可能になるわけだ。もう、__proto__
を使用する必要は皆無だね!
var obj = Object.create(null); var proto = { hello: function() { return "hello world"; }, }; Object.setPrototype(obj, proto); obj.hello(); // => "hello world" obj.hasOwnProperty("hello") // => false Object.getPrototypeOf(obj) === proto; // => true
素晴らしいですね。
Chrome (V8エンジン) では
GoogleChrome(27.0.1425.2 dev-mあたり) の __proto__ 挙動が変わった - hogehoge で V8エンジンもObject.prototype.__proto__
が定義されるようになったけど、
{ value: null, writable: true, enumerable: false, configurable: true }
とgetter/setterになっていないため、Object.setPrototypeOf
を作り出すことは不可能。