4

これらの機能の動作に違いはありますか?最初のものは、コンストラクタを考えるときに私が考えるもののより典型的なものです。コンストラクタを使用してオブジェクトを作成する方法とオブジェクトを返す方法の違いはありますか?

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

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

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

例2:新しいを使用して、オブジェクトを返すだけの機能自体を呼び出します。

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

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

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

私が理解しようとしているのは、これらがオブジェクトを作成する方法が異なる場合です。もしそうなら、他のものよりも優れていますか?誰かが他の人よりもうまくいく異なる状況がありますか?

+2

リテラルを返すと、コンストラクタ関数の '.prototype' propsで継承が提供されません。継承が必要な場合は、 "new" +コンストラクタを使用します。そうでない場合は、2番目のコードのようなファクトリを使用します。 – dandavis

+2

2番目のスニペットでは、 'new'は無視されます。 'Movie.prototype'から継承した空のオブジェクトが不必要に作成されます。ファクトリ関数で 'new'を使わないでください。そして、いいえ、彼らは同じように動作しません。 – Bergi

+0

もう1つは使用しないでください。ここでMovie.prototypeから継承することはもうありません。例えば 'other/best instanceof Movie // false false'を返します。私はこれを読むことをお勧めします:https://zetafleet.com/blog/2014/12/back-to-basics-javascript-functions-constructors-and-this-demystified.html#ref-5 – Kiechlus

答えて

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などを使用したい場合など、すべてが必要です。結局のところ、それはすべて優先事項です。

2

最初のコンストラクタはコンストラクタであるため、prototypeで拡張することができ、結果はinstanceofでテストできます。その結果はこのタイプのインスタンスです。 マイナス面:あなたが忘れてしまった場合newは(あなたが各constuctorにそのための回避策を記述しない限り)あなたのコードが

を爆破します-keywordとするとき、あなたが本当に、引数の配列を渡すために、コンストラクタでapply()を使用することはできません新しいObjectをインスタンス化します。たとえあなたが/できれば、それをしないでください。

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); 

を何かをキャストする方法としてそれを使用することができます私は、このアプローチで両方の世界のメリットを得ています。

0

違いは、返されるオブジェクトを作成するために使用されるコンストラクタです。

new Book('A Good Book', '500 pages'); 

インスタンスがBookconstructorプロパティ値を含む、Book.prototypeからプロパティを継承すると、Bookオブジェクトのインスタンスを作成します。 Book.prototypeオブジェクト自体はObject.prototypeから継承されます。

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

ファクトリ関数(newは必須ではない)としてMovieを使用してインスタンスがObjectconstructorプロパティ値を含む、Object.prototypeから直接プロパティを継承して、オブジェクトのオブジェクトのインスタンスを返します。

さらに簡単に述べると、オブジェクトリテラル構文はObjectオブジェクトを作成します。

関連する問題