カイル・シンプソンのOLOOパターンvsプロトタイプ設計パターン


109

カイル・シンプソンの「OLOO(他のオブジェクトにリンクするオブジェクト)パターン」は、プロトタイプのデザインパターンとどう違うのですか?「リンク」(プロトタイプの動作)を具体的に示し、ここで「コピー」する必要がないこと(クラスの動作)を明確にすることを除いて、彼のパターンは正確に何を導入していますか?

これは、彼の著書「You Do n't Know JS:this&Object Prototypes」からのカイルのパターンの例です

var Foo = {
    init: function(who) {
        this.me = who;
    },
    identify: function() {
        return "I am " + this.me;
    }
};

var Bar = Object.create(Foo);

Bar.speak = function() {
    alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");

b1.speak(); // alerts: "Hello, I am b1."
b2.speak(); // alerts: "Hello, I am b2."

2
少なくとも、質問しているパターンの説明にリンクできますか。あなたの質問にそれのコード例を示すことはさらに良いでしょう。
jfriend00

4
GetifyはStackoverflowにある場合があります。私は彼にこの質問をつぶやきました:)
2015

回答:


155

彼のパターンは正確に何を紹介していますか?

OLOOは、他の(IMOの混乱を招く)セマンティクスを階層化してリンクを取得する必要なく、プロトタイプチェーンをそのまま採用します。

したがって、これらの2つのスニペットはまったく同じ結果になりますが、そこに到達する方法は異なります。

コンストラクターフォーム:

function Foo() {}
Foo.prototype.y = 11;

function Bar() {}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.z = 31;

var x = new Bar();
x.y + x.z;  // 42

OLOOフォーム:

var FooObj = { y: 11 };

var BarObj = Object.create(FooObj);
BarObj.z = 31;

var x = Object.create(BarObj);
x.y + x.z;  // 42

どちらのスニペットでも、xオブジェクトは[[Prototype]]オブジェクト(Bar.prototypeまたはBarObj)にリンクされ、オブジェクトは3番目のオブジェクト(Foo.prototypeまたはFooObj)にリンクされます。

関係と委任はスニペット間で同じです。メモリ使用量はスニペット間で同じです。多くの「子」(別名、多くのオブジェクトが好きで作成する機能x1を通じてx1000、など)スニペット間で同一です。委任(x.yおよびx.z)のパフォーマンスは、スニペット間で同じです。オブジェクト作成パフォーマンス OLOOでは遅くなりますが、サニティチェックを行うと、パフォーマンスの低下は問題にはなりません。

私がOLOOが提供しているのは、オブジェクトを表現して直接リンクする方が、コンストラクター/ newメカニズムを介して間接的にリンクするよりもはるかに簡単だということです。後者はクラスについてのふりをしますが、実際には委任を表現するためのひどい構文にすぎません(補足: ES6もそうです)class構文!)。

OLOOはちょうど中間者を切り捨てています。

これがOLOO との比較ですclass


2
私はあなたの本に記述されているあなたの答えとOLOOのアイデアが本当に興味深いと思いました。この質問についてのフィードバックをお願いします:stackoverflow.com/questions/40395762/… 特に、この実装が正しく、アクセスに関連する問題を解決する方法を見つけた場合プライベートメンバー。事前にお時間をいただき、最新の本をお送りいただきありがとうございます。
GibboK 2016年

しかしObject.create(...)、何倍も遅いですnewjsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/...
桟橋

3
@Pierパフォーマンスは実際にはそれほど問題ではありません。これについて適切に考える方法を説明する、オブジェクト作成のパフォーマンスの正常性チェックに関する壊れたブログ投稿リンクを修正しました。
カイルシンプソン

2
そして、jQueryはDOM APIよりも低速ですよね?しかし、それは今年です。最適化について心配するよりも、エレガントでシンプルに書いた方がいいです。後でマイクロ最適化する必要がある場合は、その時が来たら心配します。
Eirik Birkeland

6
それを追加したいと思います。ちょうど1年後、Object.create()はchromeで大幅に最適化され、jsperfがそれを示します-これは現在最速のオプションの1つです。これは、そのようなマイクロ最適化に関心を向けるべきではなく、アルゴリズム的に健全なコードを記述する理由を正確に示しています。
カイルベイカー

25

カイルの本を読んだとき、それが本当に有益であることがわかりましたthis

長所:

私には、OLOOの大きな長所がいくつかあります。

1.シンプルさ

OLOOは、別のオブジェクトにリンクされObject.create()た新しいオブジェクトの作成に依存してい[[prototype]]ます。関数が持っていることを理解する必要はありませんprototypeプロパティたり、その変更に起因する潜在的な関連する落とし穴について心配したりする必要はありません。

2.より簡潔な構文

これは議論の余地がありますが、OLOO構文は(多くの場合)「標準」のJavaScriptアプローチよりも簡潔で簡潔であると感じています(特にポリモーフィズム(super-style呼び出し)の場合)。

短所:

私は1つの疑わしいデザインのビット(実際には上記のポイント2に寄与するもの)があると思います、そしてそれはシャドウイングに関係しています:

振る舞いの委任では、[[Prototype]]チェーンのさまざまなレベルで同じ名前を付けることは可能な限り避けます。

これの背後にある考え方は、オブジェクトが独自のより具体的な関数を持ち、それが内部的にチェーンの下位の関数に委任されるというものです。たとえば、サーバーにオブジェクトのJSONバージョンを送信resourceするsave()関数が含まれているオブジェクトがある場合がありclientResourceますが、stripAndSave()、サーバーに送信されるべきではないプロパティを最初に削除関数ます。 。

潜在的な問題は次のとおりです。他の誰かが一緒に来て、作ることを決定した場合specialResource、オブジェクトを、全体のプロトタイプチェーンを十分に認識していない、彼らは合理*と呼ばれるプロパティの下の保存、最後のタイムスタンプを保存することを決定するかもしれないsaveベース影、save()上の機能をresourceオブジェクトのプロトタイプチェーンダウン二つのリンク:

var resource = {
  save: function () { 
    console.log('Saving');
  }
};

var clientResource = Object.create(resource);

clientResource.stripAndSave = function () {
  // Do something else, then delegate
  console.log('Stripping unwanted properties');
  this.save();
};

var specialResource = Object.create( clientResource );

specialResource.timeStampedSave = function () {
  // Set the timestamp of the last save
  this.save = Date.now();
  this.stripAndSave();
};

a = Object.create(clientResource);
b = Object.create(specialResource);

a.stripAndSave();    // "Stripping unwanted properties" & "Saving".
b.timeStampedSave(); // Error!

これは、特に不自然な例であるが、ポイントは、それが具体的でありません不自然な他のプロパティをシャドウしと、厄介な状況やシソーラスの多用につながる可能性があるということです。

おそらくこれのより良い説明はinitメソッドでしょう-OOLOがコンストラクター型の関数を回避するので、特に痛烈です。関連するすべてのオブジェクトがそのような関数を必要とする可能性が高いため、適切に名前を付けるのは面倒な作業であり、一意であるため、どちらを使用するかを覚えにくい場合があります。

*実際にlastSavedはそれほど合理的ではありません(はるかに優れていますが、単なる例です。)


23
名前の衝突の可能性は欠点であると私は同意します...しかし実際にはそれは[[Prototype]]システム自体の欠点であり、特にOLOOではありません。
カイルシンプソン

おそらくそれは本でも言及されるべきだったのでしょうか?
2017

これがsave()をそれ自体の名前空間に移動するだけなので、@ Ed Hinchliffeが説明する問題の本当に解決策であるかどうかは本当にわかりませんが、それは機能しますcodepen.io/tforward/pen/govEPr?editors=1010
Tristan Forward

@ ed-hinchliffe は、コードスニペットの最終行ではb.timeStampedSave();なく、という意味だと思いますa.timeStampedSave();
amangpt777

1
@ tristan-forwardリックとモーティをここに連れてきてくれてありがとう!
エリックBishard

13

「あなたはJSを知らない:this&Object Prototypes」での議論とOLOOのプレゼンテーションは考えさせるものであり、私はこの本を読み進むことを学びました。OLOOパターンの利点は、他の回答でよく説明されています。しかしながら、私は以下のペットの不満を持っています(または私が効果的に適用するのを妨げる何かが欠けています):

1

「クラス」が古典的なパターンで別の「クラス」を「継承」する場合、2つの関数は同様の構文(「関数宣言」または「関数ステートメント」)で宣言できます。

function Point(x,y) {
    this.x = x;
    this.y = y;
};

function Point3D(x,y,z) {
    Point.call(this, x,y);
    this.z = z;
};

Point3D.prototype = Object.create(Point.prototype);

対照的に、OLOOパターンでは、ベースと派生オブジェクトを定義するために使用されるさまざまな構文形式:

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    }
};


var Point3D = Object.create(Point);
Point3D.init = function(x,y,z) {
    Point.init.call(this, x, y);
    this.z = z;
};

上記の例でわかるように、ベースオブジェクトはオブジェクトリテラル表記を使用して定義できますが、派生オブジェクトには同じ表記を使用できません。この非対称性は私を悩ませます。

2

OLOOパターンでは、オブジェクトの作成は2つのステップです。

  1. コール Object.create
  2. オブジェクトを初期化するには、いくつかのカスタムの非標準メソッドを呼び出します(オブジェクトごとに異なる可能性があるため、覚えておく必要があります)。

     var p2a = Object.create(Point);
    
     p2a.init(1,1);

対照的に、Prototypeパターンでは標準演算子を使用しますnew

var p2a = new Point(1,1);

古典的なパターンでは、「クラス」関数に直接割り当てることにより(「」ではなく)、「インスタント」に直接適用されない「静的」ユーティリティ関数を作成できます.prototype。例えばsquare、以下のコードのような関数:

Point.square = function(x) {return x*x;};

Point.prototype.length = function() {
    return Math.sqrt(Point.square(this.x)+Point.square(this.y));
};

対照的に、OLOOパターンでは、[[プロトタイプ]]チェーンを介して)オブジェクトインスタンスでも「静的」関数を使用できます。

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    },
    square: function(x) {return x*x;},
    length: function() {return Math.sqrt(Point.square(this.x)+Point.square(this.y));}
};

2
最初のコード例にはリテラルはありません。おそらく「リテラル」という用語を誤用して、別の意味を与えています。ただ言う...
Ivan Kleshnin

2
2番目の点に関して、作成者は作成と初期化を分離することが懸念の「より良い」分離であると主張し、これが光るいくつかのまれなユースケースがあるかもしれないと言及します(例:オブジェクトプール)。議論はひどく弱いと思う。
2017

2
2つ目のポイントについても、OLOOでは一度にオブジェクトを作成して初期化を待つことができますが、コンストラクターでは作成時に初期化する必要があるため、Kyleはこれをメリットと考えています。
taco

5

「私はそれが各オブジェクトを他のオブジェクトに依存させるようにすることを考えました」

カイルが2つのオブジェクトが[[Prototype]]リンクされると説明するように、それらは実際には互いに依存していません。代わりに、それらは個別のオブジェクトです。あるオブジェクトを別のオブジェクトに[[Prototype]]リンクします。リンケージはいつでも変更できます。OLOOスタイルを介して作成された2つの[[Prototype]]リンクされたオブジェクトを相互に依存していると考える場合、constructor呼び出しによって作成されたオブジェクトについても同様に考える必要があります。

var foo= {},
    bar= Object.create(foo),
    baz= Object.create(bar);


console.log(Object.getPrototypeOf(foo)) //Object.prototype

console.log(Object.getPrototypeOf(bar)) //foo

console.log(Object.getPrototypeOf(baz)) //bar

今、あなたが考えるやる秒で考えるfoo barと、baz、それぞれ、他に依存していると?

今度は同じconstructorスタイルのコードをやってみましょう-

function Foo() {}

function Bar() {}

function Baz() {}

Bar.prototype= Object.create(Foo);
Baz.prototype= Object.create(Bar);

var foo= new Foo(),
    bar= new Bar().
    baz= new Baz();

console.log(Object.getPrototypeOf(foo)) //Foo.prototype
console.log(Object.getPrototypeOf(Foo.prototype)) //Object.prototype

console.log(Object.getPrototypeOf(bar)) //Bar.prototype
console.log(Object.getPrototypeOf(Bar.prototype)) //Foo.prototype

console.log(Object.getPrototypeOf(baz)) //Baz.prototype
console.log(Object.getPrototypeOf(Baz.prototype)) //Bar.prototype

後者は前者コードW唯一の違いBは/後者であることが foobarbazbbjectsは、それらの任意のオブジェクトを介して、相互に連結されているconstructor(関数Foo.prototypeBar.prototypeBaz.prototype)が、前者(IN OLOOスタイル)は、それらが直接連結されています。あなただけリンクしているどちらかの方法foobarbaz直接前者にし、間接的に後者では、お互いに。ただし、どちらの場合でも、オブジェクトは互いに独立しています。これは、一度インスタンス化されると、他のクラスから継承することができないクラスのインスタンスとはあまり似ていないためです。オブジェクトが委任するオブジェクトもいつでも変更できます。

var anotherObj= {};
Object.setPrototypeOf(foo, anotherObj);

つまり、それらはすべて互いに独立しています。

「私はOLOO、各オブジェクトが他のオブジェクトについて何も知らないという問題を解決することを望んでいました。」

はい、それは確かに可能です-

Techユーティリティオブジェクトとして使用しましょう

 var Tech= {
     tag: "technology",
     setName= function(name) {
              this.name= name;
}
}

リンクしたいオブジェクトをいくつでも作成できますTech-

var html= Object.create(Tech),
     css= Object.create(Tech),
     js= Object.create(Tech);

Some checking (avoiding console.log)- 

    html.isPrototypeOf(css); //false
    html.isPrototypeOf(js); //false

    css.isPrototypeOf(html); //false
    css.isPrototypeOf(js); //false

    js.isPrototypeOf(html); //false
    js.isPrototypwOf(css); //false

    Tech.isPrototypeOf(html); //true
    Tech.isPrototypeOf(css); //true
    Tech.isPrototypeOf(js); //true

あなたは思いますかhtmlcssjsオブジェクトはそれぞれ、相互に接続されていますか?いいえ、そうではありません。次に、constructor関数でそれを行う方法を見てみましょう。

function Tech() { }

Tech.prototype.tag= "technology";

Tech.prototype.setName=  function(name) {
              this.name= name;
}

リンクしたいオブジェクトをいくつでも作成できますTech.proptotype-

var html= new Tech(),
     css= new Tech(),
      js= new Tech();

一部のチェック(console.logを回避)-

html.isPrototypeOf(css); //false
html.isPrototypeOf(js); //false

css.isPrototypeOf(html); //false
css.isPrototypeOf(js); //false

js.isPrototypeOf(html); //false
js.isPrototypeOf(css); //false

Tech.prototype.isPrototypeOf(html); //true
Tech.prototype.isPrototypeOf(css); //true
Tech.prototype.isPrototypeOf(js); //true

どのようにこれら思いますconstructorスタイルオブジェクトを(htmlcssjs)オブジェクトは、異なるOLOOスタイルのコード?実際、それらは同じ目的を果たします。でOLOOスタイルの一つに、デリゲートオブジェクトTechにしながら、(委任が明示的に設定された)constructorスタイルの一つに、デリゲートオブジェクトTech.prototype(委任が暗黙的に設定されました)。最終的に、OLOO-styleを直接使用して間接的に-style を使用して、3つのオブジェクトを相互にリンクせずに1つのオブジェクトにリンクすることになりますconstructor

「現状のまま、ObjBはObjA .. Object.create(ObjB)などから作成する必要があります」

いいえ、ObjBここはクラスのインスタンス(クラシックベースの言語)とは異なり ObjAます。作成時にオブジェクトがオブジェクトにデリゲートされるように言うobjBことができObjAます。コンストラクターを使用した場合、.prototypes を使用することで間接的にではありますが、同じ「カップリング」を行うことになります。


3

@マーカス@bholben

おそらく私たちはこのようなことをすることができます。

    const Point = {

        statics(m) { if (this !== Point) { throw Error(m); }},

        create (x, y) {
            this.statics();
            var P = Object.create(Point);
            P.init(x, y);
            return P;
        },

        init(x=0, y=0) {
            this.x = x;
            this.y = y;
        }
    };


    const Point3D = {

        __proto__: Point,

        statics(m) { if (this !== Point3D) { throw Error(m); }},

        create (x, y, z) {
            this.statics();
            var P = Object.create(Point3D);
            P.init(x, y, z);
            return P;
        },

        init (x=0, y=0, z=0) {
            super.init(x, y);
            this.z = z;
        }
    }; 

もちろん、Point2DオブジェクトのプロトタイプにリンクするPoint3Dオブジェクトを作成するのはばかげていますが、それは重要な点の横にあります(私はあなたの例と一致させたかったのです)。とにかく、苦情に関する限り:

  1. 非対称性は、ES6のObject.setPrototypeOf、または__proto__ = ...私が使用することで不快感を抱くことで修正できます。また、に示すように、通常のオブジェクトでsuperを使用することもできますPoint3D.init()。別の方法は次のようなことです

    const Point3D = Object.assign(Object.create(Point), {  
        ...  
    }   

    構文は特に好きではありませんが。


  1. 我々は常にちょうどラップすることができp = Object.create(Point)、その後、p.init()コンストラクタに。例えばPoint.create(x,y)。上記のコードを使用Point3Dして、次の方法で「インスタンス」を作成できます。

    var b = Point3D.create(1,2,3);
    console.log(b);                         // { x:1, y:2, z:3 }
    console.log(Point.isPrototypeOf(b));    // true
    console.log(Point3D.isPrototypeOf(b))   // true

  1. 私はこのハックを思いついて、OLOOで静的メソッドをエミュレートしました。私はそれが好きかどうかわかりません。「静的」メソッドの上部で特別なプロパティを呼び出す必要があります。たとえば、Point.create()メソッドを静的にしました。

        var p = Point.create(1,2);
        var q = p.create(4,1);          // Error!  

または、ES6 シンボルを使用して、Javascript基本クラスを安全に拡張できます。したがって、コードをいくつか保存して、Object.prototypeに特別なプロパティを定義できます。例えば、

    const extendedJS = {};  

    ( function(extension) {

        const statics = Symbol('static');

        Object.defineProperty(Object.prototype, statics, {
            writable: true,
            enumerable: false,
            configurable: true,
            value(obj, message) {
                if (this !== obj)
                    throw Error(message);
            }
        });

        Object.assign(extension, {statics});

    })(extendedJS);


    const Point = {
        create (x, y) {
            this[extendedJS.statics](Point);
            ...


2

@james emanon-つまり、多重継承について言及している(本の「JSがわからない:this&Object Prototypes」の75ページで説明されている)。そして、そのメカニズムは、たとえばアンダースコアの「拡張」関数で見つけることができます。あなたの例で述べたオブジェクトの名前は、リンゴ、オレンジ、キャンディーを少し混ぜたものですが、私はその背後にあるポイントを理解しています。私の経験から、これはOOLOバージョンです:

var ObjA = {
  setA: function(a) {
    this.a = a;
  },
  outputA: function() {
    console.log("Invoking outputA - A: ", this.a);
  }
};

// 'ObjB' links/delegates to 'ObjA'
var ObjB = Object.create( ObjA );

ObjB.setB = function(b) {
   this.b = b;
}

ObjB.setA_B = function(a, b) {
    this.setA( a ); // This is obvious. 'setA' is not found in 'ObjB' so by prototype chain it's found in 'ObjA'
    this.setB( b );
    console.log("Invoking setA_B - A: ", this.a, " B: ", this.b);
};

// 'ObjC' links/delegates to 'ObjB'
var ObjC = Object.create( ObjB );

ObjC.setC = function(c) {
    this.c = c;  
};

ObjC.setA_C = function(a, c) {
    this.setA( a ); // Invoking 'setA' that is clearly not in ObjC shows that prototype chaining goes through ObjB all the way to the ObjA
    this.setC( c );
    console.log("Invoking setA_C - A: ", this.a, " C: ", this.c);
};

ObjC.setA_B_C = function(a, b, c){
    this.setA( a ); // Invoking 'setA' that is clearly not in ObjC nor ObjB shows that prototype chaining got all the way to the ObjA
    this.setB( b );
    this.setC( c );
    console.log("Invoking setA_B_C - A: ", this.a, " B: ", this.b, " C: ", this.c);
};

ObjA.setA("A1");
ObjA.outputA(); // Invoking outputA - A:  A1

ObjB.setA_B("A2", "B1"); // Invoking setA_B - A:  A2  B:  B1

ObjC.setA_C("A3", "C1"); // Invoking setA_C - A:  A3  C:  C1
ObjC.setA_B_C("A4", "B2", "C1"); // Invoking setA_B_C - A:  A4  B:  B2  C:  C1

これは単純な例ですが、示されている点は、かなりフラットな構造/形式でオブジェクトをチェーンしているだけで、複数のオブジェクトのメソッドとプロパティを使用できる可能性があることです。クラス/「プロパティのコピー」アプローチと同じことを実現します。カイル(114ページ、「this&Object Prototypes」)によって合計:

言い換えると、実際のメカニズム、つまりJavaScriptで利用できる機能にとって重要なことの本質は、オブジェクトが他のオブジェクトにリンクされているということです

より自然な方法は、チェーン全体をモデル化するのではなく、すべての「親」(注意:)オブジェクトを1つの場所/関数呼び出しで記述することだと理解しています。

それに必要なのは、それに従ってアプリケーションの問題の考え方とモデリングを変えることです。私もそれに慣れてきました。それが役に立って、カイル自身からの最終的な評決が素晴らしいことを願っています。:)


ええ-ありがとう-しかし、私はこの方法論から離れることを望んでいました。あなたがそれを持っている方法、そして私がそれを実行する方法によって、各objが他のobjに依存するからです。OLOOが問題を解決することを望んでいました。各オブジェクトは他のオブジェクトについて何も知りません。objBは、ObjA .. Object.create(ObjB)などから結合する必要があります。何か案は?
james emanon 2015年

-1

@Marcus、あなたと同じように、私はOLOOに熱心であり、最初の点で説明した非対称性も嫌いです。私は抽象性をいじって対称性を取り戻しています。のlink()代わりに使用する関数を作成できますObject.create()。使用すると、コードは次のようになります...

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    }
};


var Point3D = link(Point, {
    init: function(x,y,z) {
        Point.init.call(this, x, y);
        this.z = z;
    }
});

Object.create()は、渡すことができる2番目のパラメーターがあることに注意してください。2番目のパラメーターを利用するリンク関数を次に示します。また、カスタム設定を少し許可します...

function link(delegate, props, propsConfig) {
  props = props || {};
  propsConfig = propsConfig || {};

  var obj = {};
  Object.keys(props).forEach(function (key) {
    obj[key] = {
      value: props[key],
      enumerable: propsConfig.isEnumerable || true,
      writable: propsConfig.isWritable || true,
      configurable: propsConfig.isConfigurable || true
    };
  });

  return Object.create(delegate, obj);
}

もちろん、@ Kyleはinit()Point3Dオブジェクトの関数のシャドウイングを推奨しないと思います。;-)


これを振り返るObject.assign()Object.create()、と組み合わせることで、link()上記の機能を大幅に簡略化できると思います。その代わりに、これを使用できますfunction create(delegate, props) { return Object.assign(Object.create(delegate), props); }。さらに良いことに、アンダースコアまたはロダッシュを使用して、本当に簡潔にすることができます _.create(delegate, props)
bholben

-1

「2つ以上の」オブジェクトをOLOOする方法はありますか?すべての例は、ベースの例で構成されています(OPの例を参照)。次のオブジェクトがあるとします。「その他」の3つの属性を持つ「4番目」のオブジェクトを作成するにはどうすればよいでしょうか。あら...

var Button = {
     init: function(name, cost) {
       this.buttonName = name;
       this.buttonCost = cost;
     }
}

var Shoe = {
     speed: 100
}

var Bike = {
     range: '4 miles'
}

これらのオブジェクトは任意であり、あらゆる種類の動作を網羅できます。しかし、要点は、「n」個のオブジェクトがあり、新しいオブジェクトには3つすべてのオブジェクトが必要なことです。

与えられた例の代わりにala:

var newObj = Object.create(oneSingularObject);
    newObj.whatever..

しかし、newObject =(Button、Bike、Shoe)......

これをOLOOで実行するためのパターンは何ですか?


1
これは、「継承よりも構成を優先する」ように聞こえる-優れた戦略。ES6では、使用することができますObject.assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...を。ES5で作成する場合は、アンダースコア_.extend()またはロダッシュを使用できます_.assign()。ここに説明する優れたビデオがあります... youtu.be/wfMtDGfHWpA。競合するプロパティがある場合は、最後のプロパティが優先されます-順序が重要です。
bholben 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.