9

JSでさまざまな継承手法を試したところ、Crockfordのプロトタイプの継承パターンについて少し不快なものに出くわしました。

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

var C,
    P = {
         foo:'bar',
         baz: function(){ alert("bang"); }
         }

C = object(P);

コンソールにログインする場合を除いて、すべて問題ありません。オブジェクトはFとして表示されます。コンストラクターを再ポイントできる従来のエミュレーションを見てきましたが、オブジェクト(コンソール)参照を強制する同様の方法はありますか?

4

2 に答える 2

14

問題はname、コンストラクター関数のを参照していることです。これはすぐに関数の式とステートメント、およびnameプロパティについての議論になります。evalを使用せずに実行時に新しい名前付き関数を作成することは完全に不可能であることが判明しました。名前は関数ステートメントを使用してのみ指定できfunction fnName(){}、コードのチャンクを回避する以外に動的に構築することはできません。var fnExpression = function(){}結果として、変数に無名関数が割り当てられます。関数のnameプロパティは不変であるため、完了した取引です。また、evalに似ているにもかかわらず、のみを使用Function("arg1", "arg2", "return 'fn body';")すると無名関数を生成できます。

これは基本的にJS仕様の見落としであり(Brendan Eichは、10年ほど前と同じように表示名を定義したことを後悔していると述べています)、ES6の解決策が検討されています。これにより、デバッグツールの関数の表示名を導出するためのより多くのセマンティクス、またはおそらくそれを設定および調整するための明示的な方法が導入されます。

今のところ、1つのルートがあります。eval、または構成可能なコードの遅延実行の他の形式です。(他の名前で評価...)

function displayName(name, o){
  var F = eval("1&&function "+name+"(){}");
  F.prototype = o; 
  return new F;
}

関数ステートメントだけではevalから返されませんが、1 &&を実行すると、返されるfnStatement式に強制されます。

(Harmonyプロキシでは、evalなしで構成できる名前を報告する関数を設定することもできますが、現在Node.jsとFirefox以外では使用できません)。

ここで、クロックフォードや他の多くの人々によって攻撃されてきたすべての「邪悪な」機能がその場所を持っていることに注意します。eval、、withネイティブを拡張することはすべて、他の方法では完全に不可能である特定の技術を可能にし、機会が適切なときにそれらを使用することは間違いではありません。ほとんどの人は、その時がいつ正しいかを判断する資格がない可能性があります。私の意見evalでは、解決策を待っている間に無害に使用して貧弱な言語セマンティクスとツールを補うことは完全に受け入れられ、その評価ステートメントに任意のコードを注ぎ込まない限り、害を及ぼすことはありません。

于 2011-11-10T08:10:42.450 に答える
0

私が見ることができるオブジェクトをログに記録すると:Object { foo="bar", baz=function()}、それで私はあなたの問題を理解していません...

とにかく、Crockfordの関数の代わりにObject.create()を使用できます。

var P = {
         foo:'bar',
         baz: function(){ alert("bang"); }
         }

var C = Object.create (P);

console.log(C):

Object { foo="bar", baz=function()}

于 2012-03-06T15:12:21.093 に答える