4

これらの機能の動作に違いはありますか? 最初のものは、コンストラクターについて考えるときに私が考えるより典型的なものです。

例 1:これを使用して名前を付け、プロパティを設定します。次に、new を使用して新しい Book オブジェクトを作成します。

    function Book(name, numPages) {
        this.name = name;
        this.numPages = numPages;
    }

    var myBook = new Book('A Good Book', '500 pages');

例 2: newを使用してオブジェクトを返し、関数自体を呼び出すだけです。

    function Movie(name, numMinutes) {
        return { name:name, numMinutes:numMinutes };
    }

    var best = new Movie('Forrest Gump', '150');

    var other = Movie('Gladiator', '180');

私が理解しようとしているのは、これらがオブジェクトを作成する方法が異なるかどうかだと思いますか? もしそうなら、一方が他方より優れていますか?一方が他方よりもうまく機能するさまざまな状況はありますか?

4

3 に答える 3

2

最初のものはコンストラクターであるため、によって拡張でき、結果がこのタイプのインスタンスであるかどうprototypeかをテストできます。instanceof欠点: - キーワードを忘れるとnew、コードが爆発します (そのための回避策をそれぞれに書かない限りconstuctor)

apply()また、新しいオブジェクトをインスタンス化するときに、コンストラクターを使用して引数の配列を渡すことは実際にはできません。一方、たとえできる/できたとしても、それをしないでください。

2 つ目は、コンストラクターではなくファクトリーです。-キーワードを使用するかどうnewかに関係なく。この実装では、同じように見えるが型やプロトタイプを共有しないオブジェクトを作成します (ただし、基礎となる JS エンジンはそれらを類似していると認識し、同じプロパティを持っている限り、同じ隠しクラスを共有します。同じ順序、... 別のトピック)
簡単に言えば、パフォーマンスもメモリフットプリントも、このアプローチの影響を受けません (もう)

ただし、それらが同じタイプであるかどうかを確認することはできず、すべてのインスタンスに影響を与える可能性のある共有プロトタイプはありません (おそらく長所または短所です)。

私のgotoアプローチ継承が必要な場合は、両方を組み合わせたものです
(データオブジェクトが必要な場合は、通常、ファクトリとプレーンオブジェクトを使用します)。

function Book(conf) {
    var book = Object.create(Book.prototype);
    //a book like this usually has multiple configs/properties
    if(typeof conf === "object"){
        for(var k in conf) book[k] = conf[k];
    }else if(conf){
        //assuming that I get at least the name passed
        book.name = String(conf);
    }
    return book;
}

//I have a prototype that can be extended
//with default-values for example; no idea for a good method 
//to add to the prototype in this example ;)
Book.prototype.numPages = 0;

//but I can also use it like a plain function; no error if you 
var myBook1 = Book("Peter Pan");
var myBook2 = Book({
    name: "American Gods",
    author: "Neil Gaiman"
});

次の行を関数の先頭に追加すると、それをメソッドとして使用して、Book既存のインスタンスを複製せずに何でもインスタンスにキャストすることもできます

function Book(conf) {
    //with this simple line I can also use this as a function to cast anything into a "Book"
    if(conf instanceof Book) return conf;

    var book = Object.create(Book.prototype);
    //...
    return book;
}

var data = [
    "Peter Pan",
    {name: "American Gods"},
    //...
];

var books = data.map(Book);

私の意見では、このアプローチには両方の利点があります。

于 2016-04-04T22:58:22.743 に答える
0

基本的に、 を使用するnewと、JS エンジンが新しいオブジェクトを作成し、それを の値として挿入しますthis。また、コンストラクターのプロトタイプにアタッチされたメソッドが自動的に提供されます。コンストラクターを使用すると、オブジェクトがinstanceof何かであるかどうかをより簡単に確認することもできます。

function MovieA(title) {
    this.title = title;
}
MovieA.prototype.getTitle = function() {
    return this.title;
};

function MovieB(title) {
    return {
    title: title
  };
}
MovieB.prototype.getTitle = function() {
    return this.title;
};

var a = new MovieA('A');
console.log(a instanceof MovieA); // true
console.log(a.getTitle()); // 'A'

var b = MovieB('B');
console.log(b instanceof MovieB); // false
console.log(b.getTitle()); // Uncaught TypeError: b.getTitle is not a function

あなたが提供するものはすべてnew他の方法で達成できますが、より多くの手作業が必要です.

2 番目の方法であるファクトリは、単体テスト、カスタム オブジェクトの作成、および関数型プログラミングに適しています。すべてのオブジェクトを生成するファクトリがある場合、そのファクトリをモックアップに置き換えてさまざまなケースをテストできるため、単体テストに適しています。

var Factory = {
  makeThing: function() {
    return { name: 'thing' };
  }
};

// Want to test the case for if makeThing fails inside of some other code
var MockFactory = {
  makeThing: function() {
    return null;
  };
};

どちらをいつ使用するかについては、すべて異なります。全く使わない人もいますnew。その他は排他的に使用しますnew。上記のものが必要かどうか、オブジェクトの作成をどの程度制御する必要があるか、いつ使用するかどうかなどによって異なりますthis。最終的には、すべて好みの問題です。

于 2016-04-04T22:29:10.960 に答える