JavaScriptのReflect

3279 ワード

前回はProxyの例を紹介しましたが、Reflectはすでに部分的に使われています.ReflectもES 6がオブジェクトを操作するために提供する新しいAPIであり、代わりにObjectを直接起動する方法である.MDN参照
今のObjectのいくつか方法、Object.definePropertyなどの底の方法は直接暴露しますが、実はあまり適切ではありません.これらの方法はObjectとReflectに同時に展開され、将来の新しい方法はReflectにのみ展開される.古いObjectの方法が使えても、できるだけReflectに切り替えるべきです.その部分は古い方法の中のいくつかの不合理なところを修正しました.例えばObject.definePropertyは属性を定義できないと異常を投げます.Reflect.definePropertyはそれをエラーに変えてfalseに戻ります.
//   
try {
    Object.defineProperty(target, property, attributes);
    ...
} catch (e) {
    ...
}

//   
if (Reflect.defineProperty(target, property, attributes)) {
    ...
} else {
    ...
}
しかも一部Object方法は命令式で、inのように、delete操作します.ReflectはReflect.hasに変更しました.Reflect.deleteProperty関数コール:
//   
var mycar = {make: "Honda", model: "Accord", year: 1998};
console.log("make" in mycar);    //true
delete mycar.model;
console.log(mycar);  //{ make="Honda",  year=1998}

//   
var mycar = {make: "Honda", model: "Accord", year: 1998};
console.log(Reflect.has(mycar, 'make'));    //true
Reflect.deleteProperty(mycar, 'model');
console.log(mycar);  //{ make="Honda",  year=1998}
Reflectの方法と前回紹介したProxyのhandlerの13の方法は一対一で対応しています.Objectの同名の方法との役割は同じです.Proxyオブジェクトの方法であれば、Reflectオブジェクトに対応する方法を見つけることができます.Proxyのブロック方法で、Reflectの同名の方法を呼び出してデフォルトの動作を実行できます.例えば、ロゴを印刷できるProxyオブジェクト:
var loggedObj = new Proxy(obj, {
    get(target, name) {
        console.log('get', target, name);
        return Reflect.get(target, name);
    },
    deleteProperty(target, name) {
        console.log('delete' + name);
        return Reflect.deleteProperty(target, name);
    },
    has(target, name) {
        console.log('has' + name);
        return Reflect.has(target, name);
    }
});
Proxyの文章で詳しく紹介されていますので、ここではReflectの同名の方法を簡単に紹介します.
get ProttotypeOf/set ProttotypeOf
Reflect.get ProttypeOfは、オブジェクトのプロトを読み取るためのObject.get ProttypeOf(obj)に対応します.
Reflect.setProttypeOfは、オブジェクトを設定するためのプロトに対応します.
isExtensioble/prevent Extensions
Reflect.isExtensioble対応Object.isExtensioble(obj)
Reflect.prevent ExtensionsはObject.prevent Extensions(obj)に相当します.
ownKeys/getOwn PropertyDescripter
Reflect.ownKeysはObject.getOwn PropertyNames.concat(Object.getOwn PropertySymbors)に相当します.
Reflect.getOwn PropertyDescriptrはObject.getOwn PropertyDescriptorに相当します.
defineProperty/deleteProperty
Reflect.defineProperty対応Object.defineProperty(obj,prop,descriptor)
Reflect.deletePropertyはdelete obj[name]に等しい.
get/set/has
Reflect.getはオブジェクトのname属性を取得するために使用します.この属性がないとundefinedに戻ります.name属性が読み取り関数を展開すると、読み出し関数のthisバインディングreceiverが与えられます.
Reflect.setは、オブジェクトのname属性の値を設定するために使用されます.name属性が賦値関数を設定している場合、赋値関数のthisバインディングreceiverが与えられます.
Reflect.hasはname in objに等しい.
appy/construct
Reflect.applyは、Funtions.prototype.apple.call(fun,thisArg,args)と同じです.Reflectの書き方は比較的簡単です.例えば、
//   
console.log(Function.prototype.apply.call(Math.floor, undefined, [1.75])); //1

//   
console.log(Reflect.apply(Math.floor, undefined, [1.75])); //1
Reflect.co nstructはnew targetに相当します.今はnewを使わずに構造関数を呼び出すことができます.
ProxyとReflectに関しては、阮一峰の『ECMAScript 6入門』を読むことができます.この二つの内容は大量にこの本を参照した.作者に感謝します.