Картина OLOO Кайла Сімпсона проти шаблону дизайну прототипу


109

Чи відрізняється «OLOO (об'єкти, що пов'язують інші об'єкти) візерунок» Кайла Сімпсона від моделі дизайну прототипу? За винятком того, як сформулювати його чимось, що конкретно вказує на "зв'язування" (поведінку прототипів) та уточнення того, що тут немає "копіювання" (поведінки класів), що саме вводить його шаблон?

Ось приклад схеми Кайла з його книги "Ви не знаєте JS: це та прототипи об'єктів":

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. Я написав йому це запитання :)
Pointy

Відповіді:


155

що саме вводить його візерунок?

OLOO охоплює прототип ланцюга таким, яким він є, без необхідності нанесення шару на іншу (IMO заплутану) семантику, щоб отримати зв'язок.

Таким чином, ці два фрагменти мають ТОЧНИЙ однаковий результат, але потрапляють туди інакше.

Форма конструктора:

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), який у свою чергу пов'язаний з третім об'єктом ( Foo.prototypeабо FooObj).

Відносини та делегування між фрагментами однакові. Використання пам'яті між фрагментами ідентично. Можливість створювати багато "дітей" (також багато предметів, таких як x1наскрізь x1000тощо) однакова між фрагментами. Виконання делегації ( x.yі x.z) однакове між фрагментами. Продуктивність створення об'єкта є повільніше Oloo, але перевіряючи коректність , що показує , що зниження продуктивності насправді не є проблемою.

Що я стверджую, що OLOO пропонує, це те, що набагато простіше просто виразити об'єкти та безпосередньо зв’язати їх, ніж опосередковано зв’язати їх через конструктор / newмеханізми. Останнє видає, що йдеться про класи, але насправді це просто жахливий синтаксис для вираження делегування ( сторона примітки: так це і classсинтаксис ES6 !).

OLOO просто вирізає середнього чоловіка.

Ось інше порівняння по classпорівнянні Oloo.


2
Я знайшов цікаву вашу відповідь та ідею OLOO, описану у ваших книгах, я хотів би отримати ваші відгуки з цього питання: stackoverflow.com/questions/40395762/… Особливо, якщо ви визнали цю реалізацію правильною та як вирішити питання, пов’язані з доступом приватний член. Заздалегідь дякую за витрачений час та вітаю за останню книгу.
GibboK

Але Object.create(...)в багато разів повільніше, ніж new. jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/…
П'єр

3
@Pier продуктивність насправді не така велика проблема. виправлено пошкоджене посилання на щоденник блогу про обгрунтованість перевірки працездатності створення об’єкта, що пояснює, як правильно думати про це.
Кайл Сімпсон

2
І jQuery повільніше, ніж API DOM, правда? Але, це поточний рік, людино - я б швидше писав елегантно і просто, ніж переймався оптимізацією. Якщо пізніше мені доведеться мікрооптимізуватись, я буду хвилюватися про це, коли настане час.
Ейрік Біркеланд

6
Я хотів би додати, що зараз, трохи більше року пізніше, Object.create () сильно оптимізований у хромі, і що jsperf показує це - це один з найшвидших варіантів зараз. Це точно показує, чому ви не повинні перейматися такими мікрооптимізаціями, а замість цього просто написати алгоритмічно звуковий код.
Кайл Бейкер

25

Я читав книгу Кайла, і вважав це справді інформативним, особливо детально про те, як thisце пов'язано.

Плюси:

Для мене є кілька великих плюсів OLOO:

1. Простота

OLOO спирається на Object.create()створення нового об'єкта, який [[prototype]]пов'язаний з іншим об'єктом. Вам не потрібно розуміти, що функції мають prototypeвластивість або турбуватися про будь-які потенційні підводні камені, що виникають внаслідок його модифікації.

2. Синтаксис чистішого

Це сперечається, але я вважаю, що синтаксис OLOO (у багатьох випадках) більш охайний і стислий, ніж "стандартний" підхід до JavaScript, особливо якщо мова йде про поліморфізм ( superстилі дзвінків).

Мінуси:

Я думаю, що є один сумнівний біт дизайну (той, який насправді сприяє пункту 2 вище), і це стосується затінення:

При делегуванні поведінки ми уникаємо, якщо взагалі можливо, називати речі однаковими на різних рівнях [[Prototype]]ланцюга.

Ідея цього полягає в тому, що об’єкти мають свої більш конкретні функції, які потім внутрішньо делегуються функціям, що опускаються вниз по ланцюгу. Наприклад, у вас може бути resourceоб’єкт з save()функцією, яка надсилає на сервер версію JSON об'єкта, але у вас може бути і 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.
Кайл Сімпсон

Можливо, це повинно було згадуватися і в книзі?
орендна плата

Я не дуже впевнений, що це справді рішення проблеми @Ed Hinchliffe описує, оскільки він просто переміщує save () до власного простору імен, але він працює codepen.io/tforward/pen/govEPr?editors=1010
Tristan Forward

Я думаю, що @ ed-hinchliffe мав на увазі b.timeStampedSave();замість a.timeStampedSave();останнього рядка фрагмента коду.
amangpt777

1
@ tristan-вперед дякую за те, що залучили Ріка та Морті до цього!
Ерік Бішард

13

Дискусія в "Ти не знаєш JS: це та прототипи об'єктів" та презентація OLOO викликає думки, і я навчився тоні переглядати книгу. Переваги схеми OLOO добре описані в інших відповідях; однак у мене є такі скарги на домашніх тварин (або я пропускаю щось, що заважає мені ефективно його застосовувати):

1

Коли "клас" "успадковує" інший "клас" за класичним малюнком, дві функції можуть бути оголошені аналогічним синтаксисом ( "декларація функції" або "функція оператора" ):

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 створення об’єкта - це два етапи:

  1. дзвінок Object.create
  2. зателефонуйте на якийсь нестандартний метод ініціалізації об'єкта (який ви повинні пам’ятати, оскільки він може відрізнятися від одного об’єкта до іншого):

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

Навпаки, у шаблоні прототипу ви використовуєте стандартний оператор new:

var p2a = new Point(1,1);

3

У класичному шаблоні я можу створити "статичні" функції утиліти, які не застосовуються безпосередньо до "миттєвого", віднести їх безпосередньо до функції "класу" (на відміну від її .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
У вашому прикладі першого коду немає літералів. Ви, мабуть, зловживаєте "буквальним" терміном, надаючи йому іншого значення. Просто кажу ...
Іван Клешнін

2
Щодо другого пункту, автор стверджує, що «краще» розділення викликає занепокоєння, коли створення та ініціалізація відокремлюються, і цитує, що може виникнути рідкісний випадок використання, коли це може світитись (наприклад, об’єктний пул). Я вважаю цей аргумент жахливо слабким.
орендна плата

2
Знову ж таки щодо другої точки, за допомогою OLOO, ви можете створити свої об’єкти одночасно і чекати ініціалізації, тоді як з конструктором ви повинні ініціалізувати створення, тому Кайл вважає це перевагою.
тако

5

"Я вважав, що це робить кожен об'єкт залежним від іншого"

Як пояснює Кайл, коли два об'єкти [[Prototype]]пов'язані, вони насправді не залежать один від одного; натомість вони є індивідуальним об'єктом. Ви пов'язуєте один об'єкт з іншим за допомогою [[Prototype]]ланки, яку ви можете змінити в будь-який час. Якщо ви приймаєте два [[Prototype]]пов'язані об’єкти, створені в стилі OLOO, як залежні один від одного, ви також повинні думати те саме про ті, що створені за допомогою 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

Єдина відмінність ч / б останнього і колишній код є те , що в останньому одному foo, bar, bazbbjects пов'язані один-одного через довільні об'єкти їх constructorфункції ( Foo.prototype, Bar.prototype, Baz.prototype) , але в колишньої ( OLOOстиль) вони пов'язані безпосередньо. Обидва способи ви просто зв'язує foo, bar, bazодин з одним, прямо в колишньому , так і побічно , в останньому. Але в обох випадках об'єкти не залежать один від одного, тому що це насправді не схожий на екземпляр будь-якого класу, який колись інстанцірований, не може бути зроблений у спадок від іншого класу. Ви завжди можете змінити, який об’єкт повинен також делегувати.

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

Як ви думаєте html, css, jsоб'єкти пов'язані один-одного? Ні, вони ні. Тепер давайте подивимось, як ми могли це зробити за допомогою 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-Style об'єктів ( html, css, js) об'єкти відрізняються від OLOO-style коди? Насправді вони служать одній і тій же цілі. В OLOO-style один об’єкт делегується Tech(делегування встановлюється явно), а в constructor-стилі один об'єкт - делегується Tech.prototype(делегування встановлюється неявно). У кінцевому підсумку ви з’єднуєте три об'єкти, не пов’язуючи один одного, з одним об'єктом, безпосередньо використовуючи OLOO-style, опосередковано використовуючи constructor-style.

"Так, ObjB має бути створений з ObjA .. Object.create (ObjB) тощо"

Ні, ObjBтут не схожий на примірник (в класичних мовах) будь-якого класу ObjA. Можна сказати, що objBоб'єкт робиться делегатом ObjAоб’єкта на час його створення " . Якщо ви використовували конструктор, ви зробили б те саме" зчеплення ", хоча і опосередковано, використовуючи .prototypes.


3

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

Звичайно, створення об’єкта Point3D, який посилається на прототип об'єкта Point2D, є якось нерозумним, але це поруч із пунктом (я хотів відповідати вашому прикладу). У будь-якому разі, що стосується скарг:

  1. Асиметрію можна виправити за допомогою Object.setPrototypeOf ES6 або більше нахмуритися на __proto__ = ...те, що я використовую. Ми також можемо використовувати супер на звичайних об'єктах і зараз, як це видно в 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 Symbols ви можете безпечно розширювати базові класи 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 - Отже, ви маєте на увазі багаторазове успадкування (обговорюється на сторінці 75 у книзі "Ви не знаєте JS: це та прототипи об'єктів"). І цей механізм ми можемо знайти, наприклад, у функції "розширення" підкреслення. Назви предметів, які ви вказали у своєму прикладі, - це трохи змішування яблук, апельсинів та цукерок, але я розумію, що за цим. З мого досвіду це буде версія 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, "Цей прототип і об'єкт"):

Іншими словами, власне механізм, суть того, що важливо для функціональності, яким ми можемо користуватися в JavaScript, полягає в тому, що об'єкти пов'язані з іншими об'єктами .

Я розумію, що більш природним способом для вас було б констатувати всі "батьківські" (обережні :)) об'єкти в одному місці / функції виклику, а не моделювання цілого ланцюга.

Для цього потрібно змінити мислення та моделювати проблеми у наших програмах відповідно до цього. Я теж звикаю. Сподіваюся, це допоможе, і остаточний вирок від самого Кайла був би чудовим. :)


Так - спасибі - але я сподівався відійти від цієї методології, тому що спосіб, який ти маєш, і те, як я зрозумів, що це зробити, робить кожен obj залежним від іншого .. Я сподівався, що OLOO вирішить проблему, в якій кожен об'єкт нічого не знає про інший. Так само, objB має бути створений з ObjA .. Object.create (ObjB) тощо., Що занадто поєднано. якісь ідеї?
Джеймс Еманон

-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()є другий параметр, який можна передавати. Ось функція посилання, яка використовує другий параметр. Це також дозволяє трохи налаштувати налаштування ...

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); }. Або ще краще, ми можемо використовувати підкреслення або Lodash , щоб зробити його дійсно коротким: _.create(delegate, props).
bholben

-1

Чи є спосіб OLOO більше, ніж "два" об'єкти .. всі приклади, які я складаю на основі прикладу (див. Приклад ОП). Скажімо, у нас були такі об'єкти, як ми можемо створити "четвертий" об'єкт, який має атрибути "інших" трьох? ала ...

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

var Shoe = {
     speed: 100
}

var Bike = {
     range: '4 miles'
}

ці об'єкти довільні і можуть охоплювати всілякі форми поведінки. Але суть полягає в тому, що у нас є «n» кількість об’єктів, і наш новий об’єкт потребує чогось із усіх трьох.

замість наведених прикладів ала:

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

АЛЕ наш новийObject = (кнопка, велосипед, взуття) ......

Яка закономірність, щоб зробити це в OLOO?


1
Це звучить як "користь композиції над спадщиною" - відмінна стратегія. У ES6 можна використовувати Object.assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . Якщо ви пишете на ES5, ви можете використовувати підкреслення _.extend()або Лодаш _.assign(). Ось чудове відео для пояснення ... youtu.be/wfMtDGfHWpA . Якщо у вас є якісь зіткненні властивості, останній виграє - значить, порядок має значення.
bholben
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.