Od 2015 roku dzięki specyfikacji ES6 a.k.a. ES2015 mamy możliwość stworzenia klasy jako reprezentacji opisu obiektu, na podstawie której zostanie on stworzony.
Co jeśli architektura Twojej aplikacji nie opiera się na klasach?
A może po prostu nie jesteś zwolennikiem Object-Oriented Programming
(OOP
)?
Taka sytuacja jest dosyć częsta, kiedy zaczynasz poznawać świat programowania w JavaScript i klasy nie są jeszcze Ci znane.
Z pomocą przychodzi wzorzec delegacji i styl Objects Linked to Other
Objects
(OLOO
), który swoją definicję posiada w książce “You Don’t Know JS”
autorstwa Kyle Simsona.
Dziedziczenie
Przykładowy model architektury w ujęciu klasycznym, czyli istnieją obiekty główne (rodzice) oraz obiekty pochodne (dzieci).
Dziedziczenie obiektów? Nie!
Model architektury opartej na OLOO nie wprowadza hierarchii. On po prostu informuje, że jeden obiekty będą korzystały z innych.
Tego procesu nie można nazwać dziedziczeniem, tylko delegacją.
W specyfikacji ES2015 została zdefiniowana funkcja statyczna
Object.setPrototypeOf
, która łączy ze sobą obiekty za pomocą wiązania
__proto__
. Wiązanie te występuje TYLKO w obiektach, w funkcjach “od zawsze”
istnieje inne wiązanie, tj: “prototype”.
const point = {
x: null,
y: null,
draw() {
// ...
}
};
const point1 = {
x: 0,
y: 0
};
console.log(typeof point1.draw); // undefined
Object.setPrototypeOf(point1, point);
console.log(point1.hasOwnProperty('draw')); // false
console.log('draw' in point1); // true
console.log(typeof point1.draw); // "function"
const point2 = {
x: 50,
y: 50
};
Object.setPrototypeOf(point2, point);
Weryfikacja
Aby móc zweryfikować aktualny stan proponuję uruchomić:
// Check: Different points
console.log(point1 !== point2) // true
// Same definition of "draw" method
console.log(point.draw === point1.draw) // true
console.log(point.draw === point2.draw) // true
console.log(point1.draw === point2.draw) // true
Wsparcie systemowe
Ale gdzie można używać takiej składni zapytasz? Otóż dzięki najpopularniejszemu zestawieniu wsparcia feature-ów JavaScript-owych, realizowanemu przez Kangax-a, możemy się dowiedzieć, że:
Jest wsparcie
- Google Chrome 57+ (Opera 44+)
- Firefox 52+
- Safari:
- desktop: 10+
- mobile: 9+
- Microsoft
- IE 11
- Edge 14+
- Node.js 4+
Brak wsparcia
Niestety, ale żaden transpiler nie pomoże w zapewnieniu wsparcia
wykorzystania funkcji Object.setPrototypeOf
:
- Babel.js
- Traceur
- Closure
- TypeScript
Link do pełnego zestawienia.
Polyfill
Link do definicji polyfilla znajduje się na MDN jednak, abyś mógł szybko zobaczyć jak on wygląda umieszczę go tutaj:
// Only works in Chrome and FireFox, does not work in IE:
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
obj.__proto__ = proto;
return obj;
}