[解決済み] JavaScriptでReflectオブジェクトは何をするのですか?
質問
少し前に MDN で空白のスタブを見かけました。
Reflect
オブジェクトの空白のスタブを見たのですが、Google でどうしても見つけることができません。今日、私はこれを見つけました
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object
を見つけたのですが、レルムとローダーの機能を除けば、Proxyオブジェクトに似ているようです。
基本的に、私が見つけたこのページは Reflect の実装方法を説明しているだけなのか、それとも私がその文言を理解できないだけなのかわかりません。どなたか、一般的に
Reflect
のメソッドが何をするものなのか、どなたか説明していただけないでしょうか。
例えば、私が見つけたページでは、次のように呼び出しています。
Reflect.apply ( target, thisArgument, argumentsList )
を呼び出すと "引数 thisArgument と args でターゲットの [[Call]] 内部メソッドを呼び出した結果を返す." と書かれていますが、これは単に
target.apply(thisArgument, argumentsList)
?
更新しました。
Blue さんのおかげで、wiki にこんなページがありました。
http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
私の知る限りでは、reflect オブジェクトは転送を容易にするためにプロキシでトラップできるすべてのアクションのメソッドバージョンを提供すると書いてある。しかし、それが完全に必要であるとは思えないので、私には少し奇妙に思えます。しかし、それはそれよりももう少し多くのことをするようです。
double-lifting
と言っていますが、これは古いプロキシ仕様を指しています。
どのように解決するのですか?
UPDATE 2015です。 で指摘されているように 7日 's 答え , ES6 (ECMAScript 2015)が確定した今、より適切なドキュメントが利用できるようになったのです。
オリジナルの回答((歴史的な)理解と余分な例のために) :
は
Reflection proposal
に進行しているようです。
ECMAScript 6 仕様書草案
. この文書では、現在
Reflect
-オブジェクトのメソッドの概要を説明し、以下の点についてのみ記述しています。
Reflect
-オブジェクト自身について以下のように記述しています。
Reflectオブジェクトは1つの普通のオブジェクトです。
Reflectオブジェクトの内部スロット[[Prototype]]の値は、標準的な組み込みObject prototypeオブジェクト(19.1.3)です。
Reflectオブジェクトは関数オブジェクトではありません。内部メソッドである [[Construct]] を持ちません。 新しい 演算子でコンストラクタとして使用することはできません。また、Reflect オブジェクトは [[Call]] 内部メソッドを持ちませんので、 Reflect オブジェクトを関数として呼び出すことはできません。
しかし、その目的についての短い説明が ES ハーモニー :
reflect "モジュールは複数の役割を担っています。
- 今、私たちはモジュールを持っているので、 "@reflect "モジュールは、以前Object上で定義された多くの反射メソッドのための、 より自然な場所です。 後方互換性の目的のために、Object上の静的メソッドが消えることはないでしょう。しかしながら、新しいメソッドは Object コンストラクタよりもむしろ "@reflect" モジュールに追加されるべきでしょう。
- プロキシのための自然なホームで、グローバルな Proxy バインディングの必要性を回避します。
- このモジュールのほとんどのメソッドは、Proxy トラップに一対一で対応します。プロキシハンドラは、以下に示すように、便利に操作を進めるためにこれらのメソッドを必要とします。
で、その
Reflect
オブジェクトは多くのユーティリティ関数を提供しますが、その多くはグローバルなオブジェクトで定義された ES5 メソッドと重複しているように見えます。
しかし、それは、これが解決しようとする既存の問題、またはどのような機能が追加されるかを本当に説明していません。私はこれがシム化されるのではないかと疑い、実際、上記の調和仕様へのリンクは これらのメソッドの非標準的な、近似的な実装' .
このコードを調べると、その使用方法について(さらに)アイデアが得られますが、ありがたいことに、このコードの概要を説明した wiki もあります。
Reflect オブジェクトが有用である多くの理由
:
(であるため、そのソースから今後の参考のために以下のテキストをコピー(およびフォーマット)しました)。
だけ
の例です。その上、それらは意味を成し、すでに良い説明を持っていて、質問の
apply
の例に触れています)。
より便利な戻り値
の多くの操作は
Reflect
で定義された ES5 の操作に似ています。
Object
のような
Reflect.getOwnPropertyDescriptor
と
Reflect.defineProperty
. しかし
Object.defineProperty(obj, name, desc)
は
obj
を返すか、プロパティが正常に定義された場合は
TypeError
を投げる。
Reflect.defineProperty(obj, name, desc)
は、プロパティが正常に定義されたかどうかを示すブーリアンを単に返すように指定されています。これによって、このコードをリファクタリングすることができます。
try {
Object.defineProperty(obj, name, desc);
// property defined successfully
} catch (e) {
// possible failure (and might accidentally catch the wrong exception)
}
これに
if (Reflect.defineProperty(obj, name, desc)) {
// success
} else {
// failure
}
このようなブール値の成功ステータスを返す他のメソッドは
Reflect.set
(プロパティを更新する) です。
Reflect.deleteProperty
(プロパティを削除する)。
Reflect.preventExtensions
(オブジェクトを拡張不可にする)、そして
Reflect.setPrototypeOf
(オブジェクトのプロトタイプリンクを更新する)。
ファーストクラスの操作
ES5 では、オブジェクトが
obj
が特定のプロパティ名を定義しているか継承しているかを検出する方法は、次のように記述します。
(name in obj)
. 同様に、あるプロパティを削除するには
delete obj[name]
. 専用の構文は短くて良いのですが、操作をファーストクラスの値として渡したい場合は、これらの操作を明示的に関数でラップしなければならないことも意味します。
とは
Reflect
を使えば、これらの操作は容易にファーストクラス関数として定義できます。
Reflect.has(obj, name)
は関数と等価で
(name in obj)
と
Reflect.deleteProperty(obj, name)
と同じことをする関数です。
delete obj[name].
より信頼性の高い機能アプリケーション
ES5 では、関数を呼び出したいとき
f
を、配列としてパックされた可変数の引数で呼び出したいとします。
args
を結合し
this
の値を
obj
と書くことができる。
f.apply(obj, args)
しかし
f
は、意図的であろうがなかろうが、自分自身を定義するオブジェクトである可能性があります。
apply
メソッドを定義しています。本当に組み込みの
apply
関数が呼ばれることを確認したい場合、典型的には次のように書きます。
Function.prototype.apply.call(f, obj, args)
これは冗長なだけでなく、すぐに理解しづらくなってしまいます。というのも
Reflect
を使えば、信頼できる関数呼び出しを、より短く、より理解しやすい方法で行うことができます。
Reflect.apply(f, obj, args)
可変引数型コンストラクタ
可変数の引数を持つコンストラクタ関数を呼び出したいとします。ES6では、新しい拡散構文のおかげで、次のようなコードを書くことができるようになります。
var obj = new F(...args)
ES5では、これは書きにくいです。
F.apply
または
F.call
を使えば、引数の数が可変の関数を呼び出すことができますが、引数の数が可変の関数には
F.construct
への関数はありません。
new
に変更すると、引数の数が可変の関数になります。と共に
Reflect
で、ES5で、書けるようになりました。
var obj = Reflect.construct(F, args)
Proxy トラップに対するデフォルトの転送動作
を使用する場合
Proxy
オブジェクトを使って既存のオブジェクトをラップする場合、操作をインターセプトして何かを行い、その後で "デフォルトの操作を行うことが非常に一般的です。例えば、あるオブジェクトへの全てのプロパティアクセスを単純に記録したいとします。
obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
// now do the default thing
}
});
は
Reflect
と
Proxy
API
は連動して設計されました。
であり、各
Proxy
のトラップに対して、対応するメソッドが存在します。
Reflect
に対応するメソッドが存在し、それは "does the default thing" です。したがって、Proxy ハンドラの内部でデフォルトの処理を行いたい場合は、常に Reflect
オブジェクトを作成します。
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
の戻り値の型は
Reflect
メソッドの戻り値の型と互換性があることが保証されています。
Proxy
トラップとの互換性が保証されます。
アクセッサのthis-bindingを制御する
ES5では、一般的なプロパティアクセスやプロパティ更新を行うのはかなり簡単です。例えば
var name = ... // get property name as a string
obj[name] // generic property lookup
obj[name] = value // generic property update
は
Reflect.get
と
Reflect.set
メソッドでも同じことができますが、さらに最後のオプション引数として
receiver
を明示的に設定することができます。
this
-バインディングを明示的に設定することができます。
var name = ... // get property name as a string
Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper`
Reflect.set(obj, name, value, wrapper)
をラップしているとき、これは時々役に立ちます。
obj
をラップしていて、アクセッサ内の自己送信をラッパーにルーティングさせたい場合。
obj
が次のように定義されている場合です。
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
呼び出し
Reflect.get(obj, "foo", wrapper)
を呼び出すと
this.bar()
にリルートされます。
wrapper
.
レガシーを避ける
__proto__
一部のブラウザで
__proto__
は、オブジェクトのプロトタイプにアクセスするための特別なプロパティとして定義されています。ES5 では、新しいメソッド
Object.getPrototypeOf(obj)
が標準化され、プロトタイプを問い合わせることができるようになりました。
Reflect.getPrototypeOf(obj)
は全く同じことをしますが、ただし
Reflect
は、対応する
Reflect.setPrototypeOf(obj, newProto)
を定義し、オブジェクトのプロトタイプを設定します。これは、オブジェクトのプロトタイプを更新する新しい ES6 準拠の方法です。
ということに注意してください。
setPrototypeOf
また
に存在する
Object
(正しく指摘されているように
クヌ
's
コメント
)!
EDITです。
余談(Qへのコメント宛)です。短くて簡単な
Q: ES6 モジュール vs. HTML インポート」についての簡単な回答があります。
で説明されています。
Realms
と
Loader
オブジェクトを作成します。
別の説明として このリンク :
<ブロッククオートrealm オブジェクトは、個別のグローバル環境という概念を抽象化したものです。 独自のグローバルオブジェクト、標準ライブラリのコピー、そして グローバル変数に束縛されない標準的なオブジェクト。 Object.prototype の初期値のような、グローバル変数に束縛されない標準的なオブジェクト) があります。
拡張可能な Web
: これは動的な同一生成元である
<iframe>
をDOM無しで表示します.
言及する価値のあるものですが これはまだ草案であり、石に刻まれた仕様ではありません! ES6なので、ブラウザの互換性には注意してください。
これが役に立つといいのですが!
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] let "と "var "の使い分けは?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] JavaScriptのオブジェクトが空であることをテストするにはどうすればよいですか?
-
[解決済み] とは何ですか! (not not)演算子とは何ですか?
-
[解決済み】JavaScript版sleep()とは?)
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
-
[解決済み] Javascript の parseInt() で先頭のゼロを削除する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] チェックボックスが選択されているかどうかを確認するjQuery
-
[解決済み] javascript の関数から `undefined` と `null` のどちらを返すのが良いのでしょうか?
-
[解決済み] TypeScriptのdeclare classとinterfaceの違いとは?
-
[解決済み] Reactコンポーネントでthis.setStateを複数回使用するとどうなりますか?
-
[解決済み] BlobからArrayBufferへ移行する方法
-
[解決済み] jQueryで入力ファイルが空かどうかをチェックする方法
-
[解決済み] なぜjavascriptのES6 Promisesはresolve後も実行を継続するのですか?
-
[解決済み] querySelectorAllがない場合、ライブラリを使用せずに属性で要素を取得する?
-
[解決済み] Fetch: ステータスがOKでない場合、プロミスを拒否し、エラーをキャッチするか?
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?