Kyle Simpson'ın OLOO Deseni ve Prototip Tasarım Modeli


109

Kyle Simpson'ın "OLOO (Diğer Nesnelere Bağlanan Nesneler) Modeli" Prototip tasarım modelinden herhangi bir şekilde farklı mı? Onu özellikle "bağlanmayı" (prototiplerin davranışı) gösteren bir şeyle kodlamaktan ve burada "kopyalamanın" olmadığını (sınıfların bir davranışı) açıklığa kavuşturmaktan başka, kalıbı tam olarak neyi ortaya koyuyor?

İşte Kyle'ın modelinin bir örneğidir onun kitabından "Sen bilir JS yapın: Bu & Nesne prototipleri",:

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
En azından sorduğunuz modelin açıklamasına bağlantı verebilir misiniz? Daha da iyisi, sorunuzda bunun bir kod örneğini göstermek olacaktır.
jfriend00

4
Getify bazen Stackoverflow'da. Ona bu soruyu tweetledim :)
Pointy

Yanıtlar:


155

kalıbı tam olarak neyi ortaya koyuyor?

OLOO, bağlantıyı elde etmek için diğer (IMO kafa karıştırıcı) semantikler üzerinde katman oluşturmaya gerek kalmadan prototip zincirini olduğu gibi benimser.

Yani, bu iki parçacığın sonucu TAMAMEN aynıdır, ancak oraya farklı şekilde varılır.

Yapıcı Formu:

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 Formu:

var FooObj = { y: 11 };

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

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

Her iki parçacıkta da, bir xnesne [[Prototype]]bir nesneye ( Bar.prototypeveyaBarObj ) bağlanır ve bu da üçüncü nesneye ( Foo.prototypeveya FooObj) bağlanır .

Parçacıklar arasındaki ilişkiler ve yetkilendirme aynıdır. Parçacıklar arasında bellek kullanımı aynıdır. Birçok "çocuk" yaratma yeteneği (aka, çok sayıda nesne gibi x1aracılığıyla x1000vb) snippet'lerinde arasındaki aynıdır. Delegasyonun ( x.yve x.z) performansı parçacıklar arasında aynıdır. Nesne oluşturma performansı olan OLOO ile yavaş ama aklı olmadığını kontrol yavaş performans gerçekten bir sorun olmadığını ortaya koymaktadır.

OLOO'nun sunduğunu iddia ettiğim şey, nesneleri yapıcı / newmekanizmalar aracılığıyla dolaylı olarak bağlamaktan çok, nesneleri ifade etmenin ve onları doğrudan bağlamanın çok daha basit olduğudur . İkincisi, sınıflarla ilgili gibi görünür , ancak gerçekten yetkilendirmeyi ifade etmek için korkunç bir sözdizimidir ( yan not: ES6 classsözdizimi de öyle!).

OLOO, aracı adamı kesip atıyor.

İşte başka karşılaştırma ait classOLOO vs.


2
Cevabınızı ve kitaplarınızda anlatılan OLOO fikrini gerçekten ilginç buldum, bu soru hakkında geri bildiriminizi almak isterim: stackoverflow.com/questions/40395762/… Özellikle bu uygulamayı doğru bulduysanız ve erişimle ilgili sorunu nasıl çözeceğiniz özel üye. Zaman ayırdığınız için şimdiden teşekkürler ve son kitabınız için tebrikler.
GibboK

Ama Object.create(...)birçok kez daha yavaştır new. jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/…
İskele

3
@Pier performansı aslında o kadar da sorun değil. Bunun hakkında nasıl doğru şekilde düşünüleceğini açıklayan nesne oluşturma performansını kontrol etme ile ilgili bozuk blog yayını bağlantısını düzeltti.
Kyle Simpson

2
Ve jQuery, DOM API'den daha yavaştır, değil mi? Ama bu yıl, dostum - Optimize etme konusunda endişelenmektense zarif ve basit bir şekilde yazmayı tercih ederim. Daha sonra mikro optimizasyon yapmam gerekirse, zamanı geldiğinde endişeleneceğim.
Eirik Birkeland

6
Şimdi eklemek isterim ki, bir yıldan biraz daha uzun bir süre sonra, Object.create (), kromda büyük ölçüde optimize edildi ve jsperf bunu gösteriyor - şimdi en hızlı seçeneklerden biri. Bu, neden bu tür mikro optimizasyonlarla ilgilenmemeniz gerektiğini tam olarak gösterir ve bunun yerine sadece algoritmik olarak sağlam kodlar yazın.
Kyle Baker

25

Kyle'ın kitabını okudum ve onu gerçekten bilgilendirici buldum, özellikle nasıl thisciltlendiğiyle ilgili ayrıntılar .

Artıları:

Benim için OLOO'nun birkaç büyük avantajı var:

1. Basitlik

OLOO , başka bir nesneye bağlı Object.create()olan yeni bir nesne yaratmaya dayanır [[prototype]]. İşlevlerin birprototype özelliği veya modifikasyonundan kaynaklanan olası ilgili tuzaklar hakkında endişelenmenize gerek .

2. Temizleyici sözdizimi

Bu tartışılabilir, ancak OLOO sözdiziminin (çoğu durumda) 'standart' javascript yaklaşımından daha düzgün ve daha özlü olduğunu düşünüyorum, özellikle de polimorfizm söz konusu olduğunda ( super-style çağrıları).

Eksileri:

Sanırım şüpheli bir tasarım parçası var (yukarıdaki 2. maddeye gerçekten katkıda bulunan bir tane) ve bu gölgeleme ile ilgili:

Davranış yetkilendirmesinde, mümkünse, [[Prototype]]zincirin farklı seviyelerinde her şeyi aynı şekilde adlandırmaktan kaçınırız .

Bunun arkasındaki fikir, nesnelerin kendi daha özel işlevlerine sahip olmaları ve daha sonra içsel olarak zincirin altındaki işlevlere delege etmeleridir. Örneğin , sunucuya nesnenin JSON sürümünü gönderen, üzerinde resourcebir save()işlevi olan bir clientResourcenesneniz olabilir, ancak bir nesneye sahip olabilirsiniz.stripAndSave() sunucuya gönderilmemesi gerektiğini fonksiyonu, ilk kaldırır özellikleri .

Olası sorun şudur: eğer bir başkası gelir ve bir specialResourcenesne yapmaya karar verirse , tüm prototip zincirinin tam olarak farkında olmadan save, adı verilen bir özellik altında son kaydetme için bir zaman damgası kaydetmeye makul bir şekilde * karar verebilir , bu da temel save()işlevselliği gölgeler . resourcenesne prototip zincirinde aşağı iki bağlantılar:

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!

Bu özellikle contrived örnektir ama nokta özellikle olmasıdır değil gölgeleme diğer özellikler bazı garip durumlar ve bir hazine ağır kullanımına yol açabilir!

Belki de bunun daha iyi bir örneği, bir inityöntem olabilir - özellikle OOLO yapıcı tipi işlevlerini sidesteps olarak dokunaklı. İlgili her nesne muhtemelen böyle bir işleve ihtiyaç duyacağından, onları uygun şekilde adlandırmak yorucu bir egzersiz olabilir ve benzersizliği, hangisinin kullanılacağını hatırlamayı zorlaştırabilir.

* Aslında özellikle makul değil ( lastSavedçok daha iyi olurdu, ama bu sadece bir örnek.)


23
İsim çarpışmaları olasılığının bir dezavantaj olduğuna katılıyorum ... ama aslında bu [[Prototype]], özellikle OLOO'nun değil , sistemin kendisinin bir dezavantajı .
Kyle Simpson

Belki de kitapta bundan bahsedilmeliydi?
kiralar

Bunun @Ed Hinchliffe'in tarif ettiği soruna gerçekten bir çözüm olduğundan emin değilim çünkü save () 'i kendi ad alanına taşıdığı için codepen.io/tforward/pen/govEPr?editors=1010
Tristan Forward

Sanırım @ ed-hinchliffe kod parçacığının son satırı b.timeStampedSave();yerine kastetti a.timeStampedSave();.
amangpt777

1
@ tristan-forward Rick ve Morty'yi buna dahil ettiğiniz için teşekkür ederiz!
Eric Bishard

13

"JS'yi Bilmiyorsunuz: Bu ve Nesne Prototipleri" ndeki tartışma ve OLOO'nun sunumu düşündürücüdür ve kitap boyunca çok şey öğrendim. OLOO modelinin yararları diğer cevaplarda iyi tanımlanmıştır; ancak, onunla ilgili aşağıdaki evcil hayvan şikayetlerim var (veya onu etkili bir şekilde uygulamamı engelleyen bir şey eksik):

1

Bir "sınıf" "klasik kalıpta" başka bir "sınıfı" miras aldığında, iki işlev benzer sözdizimi olarak bildirilebilir ( "işlev bildirimi" veya "işlev bildirimi" ):

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

Buna karşılık, OLOO modelinde, tabanı ve türetilmiş nesneleri tanımlamak için kullanılan farklı sözdizimsel formlar:

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

Yukarıdaki örnekte görebileceğiniz gibi, temel nesne, nesne değişmez gösterimi kullanılarak tanımlanabilir, oysa aynı gösterim türetilmiş nesne için kullanılamaz. Bu asimetri beni rahatsız ediyor.

2

OLOO modelinde, bir nesne oluşturmak iki adımdır:

  1. aramak Object.create
  2. nesneyi başlatmak için bazı özel, standart olmayan bir yöntemi çağırın (bir nesneden diğerine değişebileceği için hatırlamanız gerekir):

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

Buna karşılık, Prototip modelinde standart işleci kullanırsınız new:

var p2a = new Point(1,1);

3

Klasik modelde, onları doğrudan "sınıf" işlevine (onun aksine .prototype) atayarak, doğrudan "an" a uygulanmayan "statik" yardımcı işlevler oluşturabilirim . Örneğin square, aşağıdaki koddaki benzer işlevi :

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

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

Buna karşılık, OLOO modelinde herhangi bir "statik" fonksiyon ([[prototip]] zinciri aracılığıyla) nesne örneklerinde de mevcuttur:

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
İlk kod örneğinizde değişmez değer yok. Muhtemelen "gerçek" terimi başka bir anlam vererek yanlış kullanıyorsunuz. Sadece söylüyorum ...
Ivan Kleshnin

2
İkinci nokta ile ilgili olarak yazar, yaratma ve başlatmanın ayrı olmasının "daha iyi" bir endişe ayrımı olduğunu savunur ve bunun parlayabileceği nadir kullanım durumlarının (örneğin bir nesne havuzu) olabileceğini belirtir. Tartışmayı çok zayıf buluyorum.
kiralar

2
Yine 2. noktaya gelince, OLOO ile nesnelerinizi bir seferde yaratabilir ve başlatmayı bekleyebilirsiniz, oysa kurucu ile yaratımı başlatmanız gerekir, bu yüzden Kyle bunu bir fayda olarak görür.
taco

5

"Bunu yapmanın her nesneyi diğerine bağımlı hale getireceğini düşündüm"

Kyle'ın açıkladığı gibi, iki nesne birbirine [[Prototype]]bağlandığında, bunlar gerçekten birbirine bağımlı değildir; bunun yerine bireysel nesnelerdir. İstediğiniz zaman değiştirebileceğiniz bir bağlantıyla bir nesneyi diğerine [[Prototype]]bağlıyorsunuz. OLOO tarzı ile oluşturulmuş iki [[Prototype]]bağlantılı nesneyi birbirine bağımlı olarak alırsanız, constructoraramalarla oluşturulanlar için de aynı şeyi düşünmelisiniz .

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

Şimdi aklınıza yapmak bir saniye düşünmek foo barvebaz birbirinize bağlı musunuz?

Şimdi aynı constructorstil kodunu yapalım-

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

Tek fark, b / ikinci ve eski kodu ikinci bir o w foo, bar, bazbbjects kendi keyfi nesneler aracılığıyla her-diğerine bağlanır constructor(fonksiyon Foo.prototype, Bar.prototype,Baz.prototype ), ancak öncekine (içinde OLOOdoğrudan bağlantılıdır tarzı). Sadece bağlıyoruz Her iki yol foo, bar, bazdoğrudan eski birinde ve dolaylı ikinci birinde, birbirleri ile. Ancak, her iki durumda da nesneler birbirinden bağımsızdır çünkü bir kez somutlaştırıldıktan sonra başka bir sınıftan miras alınamayacak herhangi bir sınıfın örneği gibi değildir. Bir nesnenin hangi nesneye yetki vereceğini her zaman değiştirebilirsiniz.

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

Yani hepsi birbirinden bağımsız.

" OLOOHer nesnenin diğeri hakkında hiçbir şey bilmediği sorunu çözeceğimi umuyordum ."

Evet bu gerçekten mümkün-

TechBir yardımcı nesne olarak kullanalım-

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

bağlantı kurmak istediğiniz kadar nesne oluşturun 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

Sizce html, css, jsnesneleri her-diğer bağlanır? Hayır, değiller. Şimdi bunu constructorişlevle nasıl yapabileceğimize bakalım.

function Tech() { }

Tech.prototype.tag= "technology";

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

bağlantı kurmak istediğiniz kadar nesne oluşturun Tech.proptotype-

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

Biraz kontrol (console.log'dan kaçınarak) -

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

Nasıl bu sizce constructortarzı Nesneleri ( html, css, js) Nesneler farklı OLOOtarzı kod? Aslında aynı amaca hizmet ediyorlar. Gelen OLOOtarzı birine temsilci nesneleri Techiken (heyet açıkça kuruldu) constructortarzı birine temsilci nesneleri Tech.prototype(heyet dolaylı ayarlandı). Sonuçta, birbiriyle hiçbir bağlantısı olmayan üç nesneyi doğrudan kullanarak bir nesneye bağlarsınız.OLOO -stili , dolaylı olarak constructor-stili kullanarak bağlarsınız.

"Olduğu gibi, ObjB ObjA'dan oluşturulmalıdır .. Object.create (ObjB) vb."

Hayır, ObjBburada herhangi bir sınıfın örneği (klasik tabanlı dillerde) değildir ObjA. Nesnenin, oluşturulduğu anda nesneye delege yapılması gibi söylenebilirobjBObjA . " Eğer yapıcı kullanırsanız, .prototypes kullanarak dolaylı olarak da olsa aynı 'eşleştirme'yi yapardınız .


3

@MarcusTurkiye

Belki böyle bir şey yapabiliriz.

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

Elbette, bir Point2D nesnesinin prototipine bağlanan bir Point3D nesnesi oluşturmak biraz aptalca, ama asıl mesele bu (örneğinizle tutarlı olmak istedim). Her neyse, şikayetlere gelince:

  1. Asimetri ES6'nın Object.setPrototypeOf ile veya kullandığımdan daha fazla kaşlarını çatarak düzeltilebilir __proto__ = .... Biz de kullanabilirsiniz süper görüldüğü gibi, artık çok düzenli nesneler üzerinde Point3D.init(). Başka bir yol da şöyle bir şey yapmaktır:

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

    ama özellikle sözdizimini sevmiyorum.


  1. Biz her zaman sadece sarabilirsiniz p = Object.create(Point)sonra ve p.init()bir yapıcı içine. ör Point.create(x,y). Yukarıdaki kodu kullanarak Point3Daşağıdaki şekilde bir "örnek" oluşturabiliriz .

    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'da statik yöntemleri taklit etmek için bu hack ile geldim. Beğenip beğenmediğimden emin değilim. Herhangi bir "statik" yöntemin üstünde özel bir özelliği çağırmayı gerektirir. Örneğin, Point.create()yöntemi statik hale getirdim .

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

Alternatif olarak, ES6 Symbols ile Javascript temel sınıflarını güvenle genişletebilirsiniz. Böylece kendinize biraz kod kaydedebilir ve Object.prototype üzerinde özel özelliği tanımlayabilirsiniz. Örneğin,

    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 - Yani, çoklu kalıtımdan bahsediyorsunuz ("JS'yi Bilmiyorsunuz: Bu ve Nesne Prototipleri" kitabının 75. sayfasında tartışılıyor). Ve bu mekanizma, örneğin alt çizginin "genişletme" işlevinde bulabiliriz. Örneğinizde belirttiğiniz nesnelerin isimleri biraz elma, portakal ve şekerleri karıştırıyor ama arkasındaki noktayı anlıyorum. Deneyimlerime göre bu OOLO versiyonu olacaktı:

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

Bu basit bir örnektir, ancak gösterilen nokta, nesneyi oldukça düz bir yapı / oluşum içinde birbirine zincirlediğimiz ve yine de birden çok nesneden yöntem ve özellikleri kullanma olanağımız olduğudur. Sınıf / "özellikleri kopyalama" yaklaşımıyla aynı şeyleri başarıyoruz. Kyle'ın özetlediği (sayfa 114, "bu ve Nesne Prototipleri"):

Başka bir deyişle, JavaScript'te kullanabileceğimiz işlevsellik için önemli olan şeyin özü olan gerçek mekanizma, tamamen nesnelerin diğer nesnelere bağlanmasıyla ilgilidir .

Anlıyorum ki, sizin için daha doğal bir yol, tüm "ebeveyn" (dikkatli :)) nesneleri tek bir yerde / işlev çağrısında belirtmek, tüm zinciri modellemek yerine.

Buna göre uygulamalarımızdaki düşünce ve modelleme problemlerinde ihtiyaç duyulan değişimdir. Ben de alışıyorum. Umarım yardımcı olur ve Kyle'ın son kararı harika olur. :)


Evet - teşekkürler - ama bu metodolojiden uzaklaşmayı umuyordum çünkü ona sahip olma şekliniz ve bunu yapma şeklim her bir objeyi diğerine bağımlı hale getiriyor .. OLOO'nun bu sorunu çözeceğini umuyordum. her nesne diğeri hakkında hiçbir şey bilmiyor. Olduğu gibi, objB çok bağlı olan ObjA .. Object.create (ObjB) vb. Den oluşturulmalıdır. herhangi bir fikir?
james emanon

-1

@Marcus, tıpkı senin gibi, OLOO'ya meraklıyım ve ilk noktanızda anlattığım asimetriden de hoşlanmıyorum. Simetriyi geri getirmek için bir soyutlama ile oynuyorum. link()Yerine kullanılan bir işlev oluşturabilirsiniz Object.create(). Kullanıldığında, kodunuz şuna benzeyebilir ...

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()Bunun aktarılabilecek ikinci bir parametreye sahip olduğunu unutmayın . İşte ikinci parametreyi kullanan bağlantı işlevi. Ayrıca biraz özel konfigürasyona izin verir ...

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

Elbette, @Kyle'ın init()Point3D nesnesindeki işlevi gölgelemeyi desteklemeyeceğini düşünüyorum . ;-)


Şimdi geriye dönüp baktığımda, Object.assign()ile Object.create()birleşerek link()yukarıdaki işlevi büyük ölçüde basitleştirebileceğimizi düşünüyorum . Onun yerine, bu kullanabilirsiniz: function create(delegate, props) { return Object.assign(Object.create(delegate), props); }. Ya da daha iyisi, biz gerçekten özlü yapmak için alt çizgi veya Lodash kullanabilirsiniz: _.create(delegate, props).
bholben

-1

OLOO'nun "iki" nesneden daha fazla bir yolu var mı .. temelli örnek oluşturduğum tüm örnekler (bkz. OP'nin örneği). Diyelim ki aşağıdaki nesnelere sahiptik, "diğer" üçün niteliklerine sahip "dördüncü" bir nesneyi nasıl yaratabiliriz? ala ...

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

var Shoe = {
     speed: 100
}

var Bike = {
     range: '4 miles'
}

bu nesneler keyfidir ve her tür davranışı kapsayabilir. Ancak esas, "n" sayıda nesneye sahibiz ve yeni nesnemizin üçünden de bir şeye ihtiyacı var.

verilen örnekler yerine ala:

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

AMA, yeniNesnemiz = (Düğme, Bisiklet, Ayakkabı) ......

Bunu OLOO'da devam ettirmenin modeli nedir?


1
Bu, "miras yerine kompozisyonu tercih et" gibi görünüyor - harika bir strateji. ES6'da Object.assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… kullanabilirsiniz . ES5'te yazıyorsanız, Alt _.extend()Çizgi veya Lodash'ı kullanabilirsiniz _.assign(). İşte açıklamak için mükemmel bir video ... youtu.be/wfMtDGfHWpA . Herhangi bir çarpışan özelliğiniz varsa, sonuncusu kazanır - bu yüzden sıra önemlidir.
bholben
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.