9

私は既存のコードにテストを追加する方法を学ぼうとしています - 現在、 Working Effectively With Legacy Codeを読んでいます。私は JavaScript のいくつかの原則を適用しようとしてきましたが、今はインターフェースを抽出しようとしています。

JavaScript でインターフェイスを作成する方法を検索しても、多くは見つかりませんでした。また、継承について私が見つけたのは、いくつかの異なる方法があるようです。(独自の基本クラスを作成して、継承を容易にする便利なメソッドを提供する人もいれば、関数を使用する人もいれば、プロトタイプを使用する人もいます)。

正しい方法は何ですか?JavaScript でインターフェースを抽出するための簡単な例はありますか?

4

5 に答える 5

13

非常に多くの人が非常に多くの異なることを行っているため、決定的な正しい方法はありません.多くの有用なパターンがあります.

Crockford氏は、「細心の注意を払う」か、javascript のプロトタイプの性質に対応する方法で javascript を記述することを提案しています。

もちろん、彼は続けて、Netscape が提案した元のモデルが実際には壊れていることを示しています。彼はそれを「疑似古典的」と名付け、そのモデルに従うことに伴う多くの誤った方向性と不必要な複雑さを指摘しています。

彼は解決策として「オブジェクト」関数を作成しました (現在は Object.create() として知られています)。これにより、いくつかの非常に強力なプロトタイプ パターンが可能になります。

従来の JavaScript を使用する必要がある場合、クリーンなインターフェイスを開発することは必ずしも容易ではありません。特に、通常は複数のライブラリを含む大規模なシステムを扱っており、それぞれが独自のスタイルと異なる継承パターンを実装している場合はそうではありません。一般に、継承を行うための「正しい方法」は、レガシー コードのコンテキストで適切に動作するクリーンなインターフェイスを作成できるようにするだけでなく、時間の経過とともに古い依存関係をリファクタリングして削除できるようにする方法だと思います。 .

主要なライブラリ パターン間の違いを考慮すると、自分の作業で最も成功する方法は、インターフェイスをライブラリ インターフェイスから完全に独立させることであることがわかりました。ライブラリまたはモジュールが役立つ場合は使用しますが、それに縛られることはありません。これにより、多くのコードをリファクタリングし、一部のライブラリを段階的に廃止し、後で最適化できる足場としてライブラリを使用することができました。

これらの方針に沿って、Crockford の寄生的な継承パターンに触発されたインターフェイスを作成しました。それは本当にシンプルさの勝利です。

コインの反対側では、ライブラリを選択し、それをチーム全体に適用し、その継承パターンとインターフェイス規則の両方に準拠することについて議論できると確信しています。

于 2008-10-22T03:07:02.390 に答える
6

JavaScript にはクラスはなく、オブジェクトのみです。
しかし、クラスベースのオブジェクト指向モデルをエミュレートすることを主張する場合は、これを使用できます:

関数 ChildClass() {
    ParentClass.call(これ);
    // この時点の後に残りのコンストラクター関数を記述します。
};
ChildClass.prototype = jQuery.extend({}, ParentClass.prototype, ChildClass.prototype);

jQuery.extend は、jQuery ライブラリの「浅いコピー」関数です。他のオブジェクトのコピー/クローン機能に置き換えることができます。

于 2008-10-22T03:59:01.333 に答える
5

あなたは2つの異なるものを見ています。

まず、インターフェースがあります。これを実装する最も受け入れられている方法は、ダックタイピング (「アヒルのように見え、アヒルのように鳴く場合、それはアヒルです」) です。これは、オブジェクトがインターフェイスのメソッドのセットを実装する場合、それがそのインターフェイスであることを意味します。これを実装するには、インターフェイスを定義するメソッド名の配列を用意します。次に、オブジェクトがそのインターフェイスを実装しているかどうかを確認するには、それらのメソッドを実装しているかどうかを確認します。これが私が作成したコード例です。

function Implements(obj, inter)
{
    var len = inter.length, i = 0;
    for (; i < len; ++i)
    {
        if (!obj[inter[i]])
            return false;
    }
    return true;
}

var IUser = ["LoadUser", "SaveUser"];

var user = {
        LoadUser : function()
        {
            alert("Load");
        },

        SaveUser : function()
        {
            alert("Save");
        }
    };

var notUser = {
        LoadUser : function()
        {
            alert("Load");
        }
    };

alert(Implements(user, IUser));
alert(Implements(notUser, IUser));

これで継承ができました。JS には継承が組み込まれていません。したがって、手動で実装する必要があります。これは、あるオブジェクトのプロパティを別のオブジェクトに「コピー」するだけです。別のコード サンプルを次に示します (完全ではありませんが、要点を示しています)。

function InheritObject(base, obj)
{
    for (name in base)
    {
        if (!obj[name])
            obj[name] = base[name];
    }
}

var Base = {
        BaseFunc : function() { alert("BaseFunc from base"); },
        InheritFunc : function() { alert("InheritFunc from base"); }
    }

var Inherit = {
        InheritFunc : function() { alert("InheritFunc from inherit"); },
        AnotherFunc : function() { alert("AnotherFunc from inherit"); }
    }

InheritObject(Base, Inherit);

Inherit.InheritFunc();
Inherit.BaseFunc();
Inherit.AnotherFunc();

Base.BaseFunc();
Base.InheritFunc();

おそらくhttp://www.mootools.netを見たいと思うでしょう。クラスの私のお気に入りの実装があります。「Pro Javascript Design Patterns」もぜひチェックしてください。

http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X

この本は、JavaScript で OOP をエミュレートする方法について詳しく説明しています。

于 2008-10-22T03:24:55.413 に答える
3

Dean Edwards の Base.js もチェックしてください。ここで見ることができます。ブログの投稿は一目瞭然です。

于 2008-10-22T03:15:19.737 に答える
0

Prototype は、 http://www.prototypejs.org/api/class/createから、独自の継承を提供します。

var Animal = Class.create({
  initialize: function(name, sound) {
    this.name  = name;
    this.sound = sound;
  },

  speak: function() {
    alert(this.name + " says: " + this.sound + "!");
  }
});

// subclassing Animal
var Snake = Class.create(Animal, {
  initialize: function($super, name) {
    $super(name, 'hissssssssss');
  }
});
于 2008-10-22T13:23:00.307 に答える