3

この古い質問にコメントしたかったのですが、ロックされているようです。

これが私のユースケースです:

  1. オブジェクトobjはコンストラクターで作成されBaseます。obj instanceof Basetrue を返します。
  2. のプロトタイプをから構築さobjれたかのように変更したい。つまり、欲しい objDerived
    • objのメソッドにアクセスするにはDerived
    • obj instanceof Derived真を返す

その理由はobj、作成時には不明であり、その後何が起こるかによって決定されるタイプを階層内に持つためです。階層を下に移動できるようにしたい。

私はこれを行うことができると信じています

obj.__proto__ = Derived.prototype;

しかし__proto__、次のバージョンの JavaScript では廃止される予定です。上でリンクした質問が尋ねられてから変更されたプロキシAPI は、私の使用例をサポートしていないようです。

現在存在する、または将来的に計画されているユースケースの代替実装はありますか?

私が今見ることができる唯一の代替手段は、使用することです

obj2 = Object.create(Derived.prototype);
obj2.extend(obj);

obj への複数の参照を保存することはありませんが、そのコストは非常に不便です。

これは、問題を示すフィドルです。

4

3 に答える 3

3

それをする可能性はないと思います。RobGが示したように、クラスのプロパティに害を与えることfalse変更することで、インスタンスを返すことができます。prototype

それを見て、私はあなたが一般的なシムFからのように、あなたが知っている、追加のクラスでそれを行うことができると思いました:Object.create

Object.newChangeable = function create(b) {
    function F(){b.call(this);}
    F.prototype = b.prototype;
    var f = new F();
    f.change = function change(n) {
        F.prototype = n.prototype;
    };
    return f;
}

var obj = Object.newChangeable(Base);
obj instanceof Base; // true

obj.change(Derived);

しかし、いいえ

obj instanceof Derived; // still false
obj instanceof Base; // still true

の内部[[Prototype]]はobjまだと同じを指しているからBase.prototypeです。あなたができることはDerived新しいものを作ることですBase

var obj = new Base;
obj instanceof Base; // true

Derived.prototype = Base.prototype;
Base.prototype = {}; // something else

alert(obj instanceof Derived); // true
alert(obj instanceof Base); // false

objしかし、私はそれがあなたが望んでいたことではないと思います、 :-)で何かを変更する代わりに、式の右側を操作します

于 2012-03-28T00:50:14.093 に答える
2

instanceof演算子は、コンストラクターのパブリックprototypeプロパティがオブジェクトの[[Prototype]]チェーン上にあるかどうかをチェックするだけです。チェーンを壊す 1 つの方法は、コンストラクターのプロトタイプを変更することです。

function Base() {}

var base = new Base();

alert( base instanceof Base); // true

Base.prototype = {};

alert( base instanceof Base); // false
alert( base instanceof Object); // true

2 番目のアラートは false です。これは、新しいアラートがチェーンBase.prototype上にないためです(元のアラートはまだ存在します)。まだあることに注意してください。上記は、演算子が特に有用であると見なされない理由の 1 つです。[[Prototype]]baseObject.protoyypeinstanceof

やろうとしていることを行うには、[[Prototype]]後で変更できないため、オブジェクトの構築時にチェーンを作成する必要があります。

Derived.prototype = new Base();

var base = new Derived();

alert(base instanceof Base); // true
alert(base instanceof Derived); // true

編集

要件は次のとおりです。

  1. オブジェクト obj はコンストラクタ Base で作成されます。obj instanceof Base は true を返します。

示されているように、それは必ずしも真実ではありません。特定の値を返すことに依存する戦略がある場合は、instanceof明確な利点のない設計に (おそらく不合理な) 制約を課していることになります。

2. obj が Derived から構築されたかのように見えるように、obj のプロトタイプを変更したいと考えています。つまり、欲しい

•obj は Derived のメソッドへのアクセスを取得します

これを行うには、Base.prototype を Derived のインスタンスにするか (示されているように)、プロパティを Base.prototype にコピーします。

•obj instanceof true を返すように派生

これを行うには、 Baseのインスタンスを作成する前にDerivedBase.prototypeのインスタンスを作成します。

インスタンスの作成後にチェーンを変更することはできません。instanceof制約を削除するDerived.prototypeと、 にコピーするだけで のメソッドを追加できますBase.prototype。もう 1 つの方法は、callまたはapplyを使用することです。

Derived.prototype.someMethod.call(base, ...);

しかし、あなたは不可能なことをしようとしていると思います。

于 2012-03-28T00:09:48.953 に答える
0

これは意味ですか(質問について少し混乱していて、私はまだ学習者です)

function vehicle(name, color)
{
    if(this instanceof arguments.callee)
    {    
        this.name = name;
        this.color = color;
    }
    else return new arguments.callee(arguments);   
}

vehicle.prototype = {
    getName : function()
    {
        alert(this.name);
    } 
}

function Car(name, color, speed)
{
        this.name = name;
        this.color = color;
        this.speed = speed;
}

Car.prototype = vehicle();
var obj = new Car("Ford", "Red", "200mph");

obj.getName(); // alerts `Ford` using vehicle's/parent's method
alert(obj instanceof vehicle); alerts `True` instanceof vehicle's/parent's constructor

フィドルはここにあります。

ジョン・レシグによる記事。

于 2012-03-27T23:55:27.753 に答える