1

私はJavaScriptの強力なバックグラウンドを持つアーキテクトですが、過去に.NETとJavaをいくつか実行しました。

しかし、JavaScriptに非常に関連していると約束されたActionScript3を手に入れたかったのです。

スタートアッププロジェクトとして、私は自分自身でActionScript3への移植を試みました。これは私のお気に入りのアサーションutilsの1つであるshould.jsであり、テストコードを非常に読みやすくします。

更新日:2013-02-19

アブストラクトの話と混同しているのを見たので、投稿の一部を具体的な質問に置き換えました。全体像は次のとおりです。

次のJavaScriptコードについて考えてみます。

Object.defineProperty(Object.prototype, 'should'
, { set: function(){}
  , get: 
    function(){
       return new Assertion(Object(this).valueOf());
    }
  , configurable: true
  , enumerable  : false
  }
);

これは、JavaScriptモジュールの実装の一部ですShouldAssertionもう1つの部分は、値を使用して構築され、その値に対して幅広く優れたアサーションメソッドのセットを実装するクラスの定義です。次のようなメソッド

var o = Assertion(actualValue)
o.equals(expectedValue1)
o.moreThan(expectedValue2)
o.contains(expectedValue3)

英文法を維持するためのエイリアス

var o = Assertion(actualValue)
o.equal(expectedValue1)
o.contain(expectedValue3)

怠惰な狙撃兵のエイリアス

o.eql(expectedValue)
o.gt(expectedValue) //greater then
o.gte(...) //greater then or equal
//and so on... 

そして、(テスト値thisで構築されたインスタンスである)を返すだけのいくつかのコネクタは次のようになります。Assertion

o.be
o.and

それはあなたに何を与えますか?

次のようなテストコード:

var person = getPerson();
Should.exist(person); //that's a static call, and that's easy

//but these are a member calls:
person.should.have("name","age","address","friends");  
person.name.should.equal("John");
person.age
  .should
      .be.number()
  .and.be.between(20,30);

person.address
  .should
    .be.string().and
    .startWith("\d").and
    .endWith(" st.")
  //or even
    .and.match(/^[0-9]{1,9}\s+[A-Z][a-z0-9 ]* st\.$/);

person.friends
  .should
    .be.array().and
    .be.between(3,5).and
    .containOnlyType(String);

それは素晴らしいことではありませんか?平易な英語です!

インデントの美学、どこに配置するandか、そしてそれらが必要かどうかについて議論することができますが、それ以外に-誰でもそれを読み書きできます:すべてのオブジェクトに存在するがマップを台無しにしない「should」属性を取得すると反復-あなたはあなたが始めた価値に関してあなたが主張しなければならないものは何でも連鎖し続けることができます。

より優れた反復ツール、リフレクションユーティリティ、オブジェクトモデルに関連するテスト関数などを追加することもできますが、最初のステップを乗り越えることができます:)

ただし、そのためには、システム内のすべてのオブジェクトが、そのgetter関数でテスト値としてで構築されたオブジェクトを返すという列挙不可能なスマートプロパティを備えている必要がありますshouldAssertionthis

(あなたはまだ何も見ていません-それが与える美しい拒絶メッセージを見るのを待ってください!Yummie!!そうそう-私は属性を「すべき」と呼ぶオプションを喜んで犠牲にします...そして幸いにも知性をあきらめます-少なくともそれが平易な英語である限り)

したがって、コメントで、bfavarettoは私たちに最初のステップを与えました-属性の列挙を防ぐ方法を知っています-素晴らしい&ありがとう!!

さて、関数がアクセスできるゲッター属性にすることはできますthisか?

私が終わったら、私たち全員が楽しむために、MITの下で認可されたいくつかの公開リポジトリにそれを置くつもりです:)

誰か助けますか?

4

3 に答える 3

0

私はJavascriptがどのように機能するかについてはよく知らないことを告白しますが、definePropertiesの目的を正しく理解している場合、それはプロパティがどうあるべきかだけでなく、プロパティが属する関連する名前空間(または少なくともAS3が名前空間と見なすもの)。

クラスプロパティは、事前定義されており、カスタムget()set()関数を介してのみ変更可能であるか、動的です。一度コンパイルすると、名前空間を変更することはできません(私の知る限り)。したがって、非プライベートプロパティは暗黙的に列挙可能であり、getter / setter(つまり、:)を作成したかどうかに関係なく変更できますfoo.a = valueアドビによると...

作成するプロパティは列挙可能ですが、組み込みのプロパティは通常列挙できません。

そうは言っても、describeTypeを使用すると、クラスからプロパティの完全なリストを取得できます。この方法でかなりの量の情報を収集できます。Mozillaの再作成されたdefinePropertiesの例を移植したい場合は、ニーズに合うはずです。以下は、プロパティ値のみを出力する例です。

function showProps(obj:*):void {
    var desc:XML= describeType(obj);

    // public vars
    for each (var n:XML in desc.variable){
        trace(n.@name + ": " + obj[n.@name]);
    }
    // getters
    for each (n in desc.accessor){
        try {
            trace(n.@name + ": " + obj[n.@name]);
        } catch (error:Error) {
            trace("Unable to read write-only property.");
        }
    }
}

これがお役に立てば幸いですが、あなたが何を達成しようとしているのか完全には理解していないと確信しています。あなたが詳しく説明することができれば、それはありがたいです。

于 2013-02-14T21:54:19.867 に答える
0

あなたの例は実際には90%正しいですが、javascriptではなくactionscriptのように定義してください!

AS3でプロトタイプを定義することもでき、AS2のプロトタイプと同じように機能します。AS3の唯一の違いはコンパイラです。AVM2は、何らかの理由でプロトタイプをネイティブクラスにキャストしません(ただし、カスタムクラスはテストしていません)。

プロトタイプのトリック:クラスをオブジェクトとしてキャストします。

例:作成する場合:

Array.prototype.random = function():void {}

次に、オブジェクトを作成します。

var myProtoArray:Array = new Array;

2つのことが起こります:

myProtoArray.random()//エラー-これは失敗します。AVM2はプロトタイプをアレイにマップしませんでした

しかし

Object(myProtoArray).random()// WORKS

random()がObjectクラスにキャストされ、次にArrayにマップされました-理由はわかりません!

これがお役に立てば幸いです、乾杯。

于 2013-02-14T21:50:55.990 に答える
0

さて、皆さん、すべての助けに感謝します。22歳以上元の質問に興味を持っている人々の要約を示し、その後、私の努力の結果をお見せします。

チャレンジは2つの部分で構成されていました:

1-拡張(=実行時に追加)プロパティが列挙されないようにします

最初の部分に-@bfavarettoのおかげで、質問レベルにコメントしました---Object.setPropertyIsEnumerableトリックは素晴らしかったです。

2-拡張プロパティにアクセス権を持つgetter関数を操作させてthis、戻り値のコンストラクターで使用できるようにします。

この2番目の部分について-基本的に-プロトタイプにプロパティゲッターを拡張(=追加)する方法を見つけることができず、継承ツリーを介してAPIを楽しむインスタンスで動作させることができませんでした。

とにかく、これらの制限内で-結果は次のとおりです。

https://github.com/osher/should.as

プラットフォームの違いのために正確な移植ではありません。元のshould.jsに追いつくためのいくつかのメソッド(HTTPテストメソッドなど)がまだありますが、十分に近いです。主な違いは、代わりに

var o:Object = 
    { name : "Radagast"
    , color: "Brown"
    }
o.should.have.properties("name","color")
    .and.have.property("name","Radagast");
o.name.should.not.equal("Palandoo");
o.color.should.equal("Brown");

あなたが行かなければならない

o.should().have.properties("name","color")
       and.have.property("name","Radagast");
o.name.should().not.equal("Palandoo");
o.color.should().equal("Brown");

(角かっこ-ゲッターは使用できません-したがって、should属性はメソッドであり、自分で呼び出す必要があります)

行き詰まり、インテリセンスの助けが必要な場合は、次のことを行う必要があります。

var should:tdd.Should = o.color.should();
should. <ctrl+space>

どの種類の'aは刺し傷を取り除きますが、インテリセンスを覗くために-それは役立ちます

重要

もう1つ、Shouldの静的コンストラクターをできるだけ早く実行する必要があります。たとえば、ここで実行します。

[Suite]
[RunWith("org.flexunit.runners.Suite")]
public class my_awsome_test_suite
{
            //forces the static constructor of tdd.Should
    import tdd.Should;
    private static var s:Should = new Should(); 

    public var c1:testCase1;
    public var c2:testCase2;
    public var c3:testCase3;
    public var c4:testCase4;
    }

後で適切なREADME.mdを追加し、さらに恐ろしいメンバー関数を追加しますtdd.Should

楽しむ

于 2013-03-05T20:16:10.383 に答える