48

次のように、プロキシを拡張しようとしました。

class ObservableObject extends Proxy {}

Babel を使用して ES5 にトランスパイルしたところ、ブラウザで次のエラーが表示されました。

app.js:15 Uncaught TypeError: Object prototype may only be an Object or null: undefined

それが指しているコード行を見ました。問題のあるコード行を指す矢印が付いたコードのその部分は次のとおりです。

var ObservableObject = exports.ObservableObject = function (_Proxy) {
    _inherits(ObservableObject, _Proxy); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    function ObservableObject() {
        _classCallCheck(this, ObservableObject);

        return _possibleConstructorReturn(this, Object.getPrototypeOf(ObservableObject).apply(this, arguments));
    }

    return ObservableObject;
}(Proxy);

このエラーが発生する理由を知っている人はいますか? これはBabelのバグですか?Proxy を拡張しようとするとどうなりますか?

4

6 に答える 6

38

いいえ、ES2015 クラスはProxy1を拡張できません。

プロキシ オブジェクトは非常に特殊なセマンティクスを持ち、ES2015 では「エキゾチック オブジェクト」と見なされます。つまり、「すべてのオブジェクトでサポートされなければならない 1 つ以上の重要な内部メソッドのデフォルトの動作がありません」。プロトタイプはありません。これは、拡張する型のほとんどの動作を通常取得する場所です。セクション26.2.2から:仕様の「プロキシコンストラクタのプロパティ」

プロキシ エキゾチック オブジェクトには初期化が必要な [[Prototype]] 内部スロットがないため、コンストラクターにはプロパティがありませんProxyprototype

これは Babel の制限ではありません。それとクラス構文が両方ともネイティブにサポートされている Chrome で拡張しようとするProxyと、同様のエラーが発生します。

キャッチされていない TypeError: Class extends value に有効なプロトタイプ プロパティ undefined がありません

1「いいえ」が現実的な答えです。しかし、Alexander O'Maraは、(gross!) に値を代入するProxy.prototypeと、少なくとも一部のブラウザーでは拡張可能になると指摘しました。これを少し試してみました。エキゾチックな Proxy インスタンスの動作のため、これを使用してコンストラクターをラップする関数でできる以上のことを達成することはできず、一部の動作はブラウザー間で一貫していないようです (仕様が何を期待しているかはわかりません)。これを行う場合)。深刻なコードでこのようなことを試みないでください。

于 2016-06-09T00:01:23.193 に答える
15

@John L. 自己応答から:
コンストラクター内で、Proxy を使用して新しく作成されたインスタンスをラップできます。プロキシを拡張する必要はありません。

例として、既存の Point クラスから観測点を提供します。

class Point {

    constructor(x, y) {
        this.x = x
        this.y = y
    }

    get length() {
        let { x, y } = this
        return Math.sqrt(x * x + y * y)
    }

}

class ObservedPoint extends Point {

    constructor(x, y) {

        super(x, y)

        return new Proxy(this, {
            set(object, key, value, proxy) {
                if (object[key] === value)
                    return
                console.log('Point is modified')
                object[key] = value
            }
        })
    }
}

テスト:

p = new ObservedPoint(3, 4)

console.log(p instanceof Point) // true
console.log(p instanceof ObservedPoint) // true

console.log(p.length) // 5

p.x = 10 // "Point is modified"

console.log(p.length) // 5

p.x = 10 // nothing (skip)
于 2018-03-05T10:16:45.273 に答える
0

Babel は Proxy をサポートしていません。したがって、ブラウザーがサポートを追加するまで、それは存在しません。

Babel ドキュメントから:「ES5 の制限により、サポートされていない機能のため、プロキシをトランスパイルまたはポリフィルすることはできません」

于 2016-06-09T00:01:05.157 に答える