Nagyn eltökéltnek kell lennünk ahhoz, hogy JavaScript szintaxissal a JavaScript szemléletének megfelelően tudjunk programozni. JS-re épülő nyelvekkel (CoffeeScript, TypeScript) ez könnyebben megvalósítható.
Miért van ez, mit ért a JavaScript az objektum orientáltság alatt, hogyan működik a prototípusos öröklődés, mi az a this?
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Object Oriented JavaScript
1. Object Oriented
JavaScript
avagy JavaScriptben miért
nem JavaScriptül programozunk?
Farkas Máté
Budapest.js, 2013. január 14.
2. Összefoglaló
A következőkről lesz szó
1.Objektumok létrehozása, azaz a prototípus
alapú öröklődés – kell ez nekünk?
2.Objektumok működése: metódusok,
függvények – mi az a this?
Megvizsgáljuk, hogy a gyakorlat hol
és miért tér el az elmélettől.
4. Példák
Miért kell ez?
// Mootools // YUI
var Monkey = new Class({ var Monkey = Y.Base.create('monkey',
initialize: function(name){ null, [], {
this.name = name; initializer: function(name) {
} this.name = name;
}); }
});
// Prototype
var Monkey = Class.create({ // dojo
initialize: function(name) { var Monkey = declare(null, {
this.name = name; constructor: function(name){
} this.name = name;
}); }
});
http://h3manth.com/content/classes-javascript-es6
5. Objektum Orientált JavaScript
• A JavaScript objektum orientált.
• A primitív típusokon kívül minden objektum,
még a függvények, tömbök is
• Egy objektumnak vannak tulajdonságai és
„metódusai”
• A kérdéses dolog az, hogy hogyan hozzuk létre az
objektumokat: nincsenek osztályok, prototípus
alapú az öröklődés
6. Objektum létrehozás (osztályok)
Osztály alapú objektum orientáltság
Person Viola
Osztályok közötti
Employee Ádám hierarchia, majd
példányosítás
Boss Igor
osztály példány
7. Objektum létrehozás (prototípus)
Prototípusos objektum orientáltság
PersonCreator
Objektumok közötti
Viola
hierarchia
EmployeeCreator
Ádám
BossCreator
Igor
konstruktor
függvény objektum
8. Objektum létrehozás (prototípus)
Prototípusos objektum orientáltság
PersonCreator
A konstruktor függvény
Viola egy konkrét, létező
EmployeeCreator
objektumból hoz létre
egy másikat
Ádám
BossCreator
Igor
konstruktor
függvény objektum
9. Objektum létrehozás (prototípus)
Prototípusos objektum orientáltság
PersonCreator
A konstruktor függvény a
Viola megadott „minta”
EmployeeCreator
alapján készít egy új
objektumot úgy, hogy
Ádám megmondja, miben
BossCreator
különbözik (a minta
nem része a konstruk-
konstruktor
Igor
tor függvénynek)
függvény objektum
15. A létrehozás folyamata
var adam = new EmployeeCreator();
1.Létrehoz egy új objektumot a függvénynek átadott
prototípus szerint
2.Beállítja, hogy ezt az új objektumot a függvény
hozta létre (instanceof)
3.Meghívja a függvényt, hogy inicializálja (módosítsa,
állítsa be) az új objektumot
16. Mi ezzel a baj?
PersonCreator.prototype.name = …
EmployeeCreator.prototype.salary = …
• Ha nem határozzuk meg, a függvénynek átadott
prototípus egy új üres objektum lesz
• Ezt módosítva megadhatjuk, hogy milyen
objektumokat tudjon létrehozni, de elveszítjük az
öröklés lehetőségét
18. Gyakorlat
• Ádám egy munkavállaló, 12 ezer eurós fizetéssel.
PersonCreator
Ádám
EmployeeCreator
Ádám,
12e EUR
19. Gyakorlat
• Ádám egy munkavállaló, 12 ezer eurós fizetéssel.
• Zsolt egy munkavállaló, 13 ezer eurós fizetéssel.
PersonCreator PersonCreator
Ádám Zsolt
EmployeeCreator EmployeeCreator
Ádám, Zsolt,
12e EUR 13e EUR
20. Így tud működni
function PersonCreator(name) {
this.name = name; }
function EmployeeCreator(salary) {
this.salary = salary; }
var adamPerson = new PersonCreator(‘Ádám’);
EmployeeCreator.prototype = adamPerson;
var adam = new EmployeeCreator(12);
// adam instanceof PersonCreator
// adam instanceof EmployeeCreator
21. Így tud működni
function PersonCreator(name) {
this.name = name; }
function EmployeeCreator(salary) {
this.salary = salary; }
var adamPerson = Object.create({});
PersonCreator.call(adamPerson, ‘Ádám’);
var adam = Object.create(adamPerson);
EmployeeCreator.call(adam, 12);
// ez az elmélet, de nincs instanceof,
// és nem hatékony
22. Mixinek
Előny: mixinek használata, könnyű viselkedéssel
kiterjeszteni egy objektumot
var adam = {};
PersonCreator.call(adam, ‘Ádám’);
EmployeeCreator.call(adam, 12);
DriverMixin(adam);
adam.driveTo(‘Paris’);
24. Megoldási lehetőségek
• Sok féle megoldási lehetőség van, szinte minden
library kidolgozott magának valamit
• MooTools
• Dojo
• YUI
• Prototype
• class.js (John Resig)
26. No, ez mi?
var globalScope = (function () {
return (0, eval)('this');
}());
27. No, ez mi?
var globalScope = (function () {
return (0, eval)('this');
}());
Meghívható
objektumra mutat
28. Függvény
• A JavaScriptben a függvény egy futtatható
objektum a memóriában, erre az objektumra
hivatkozhatunk sokféleképpen
• Ha egy objektum tulajdonságaként hivatkozva
hívjuk meg, akkor metódusként fog működni, és
„a függvény belsejében a this értéke az adott
objektum lesz.”
29. Függvény, metódus
function fn() {}
var b = fn; obj.c = b;
obj.getFn = function() { return fn; }
fn(); b(); obj.c(); obj.getFn()();
33. Program futási folyamat
Klasszikus program futási folyamat
Van egy hosszú futási
szálunk, ami vagy aktív,
vagy alszik, ezen belül
vannak blokkok,
függvények, stb…
35. Program futási folyamat
JavaScript program futási folyamat
doStuff
function doStuff() {
1 doAsync(function(result) {
3
4 parse(result);
5 doAsync
});
2 parse
}
36. Metódus
• Elmélet: A JavaScriptben ha egy objektum
tulajdonságaként hívunk meg egy függvényt, akkor
az az adott objektum metódusaként viselkedik, azaz
benne a this értéke az adott objektum lesz.
•
obj.greetAll = function() {
this……
};
37. Metódus
• Elmélet: A JavaScriptben ha egy objektum
tulajdonságaként hívunk meg egy függvényt, akkor
az az adott objektum metódusaként viselkedik, azaz
benne a this értéke az adott objektum lesz.
• Gyakorlat: Kivéve, ha a függvényen belül van egy
másik függvény…
obj.greetAll = function() {
this.names.forEach(function() {…});
};
38. Megoldási lehetőségek: this
• Használjunk mindenhol this-t!
• Nem működik.
obj.greetAll = function() {
this.names.forEach(function() {…});
};
39. Megoldási lehetőségek: this + bind
• Bind-oljuk a this-t, ahol kell
• CoffeeScript-nél is ezt próbálták egy időben
• A gyakorlatban nem megvalósítható.
obj.greetAll = function() {
this.names.forEach(function() {
// …
}.bind(this));
};
40. Megoldási lehetőségek: _this
• Használjunk _this-t, ahol kell
• Mehet a prototípus szerinti öröklődés, de a kódunk
nem lesz egységes (valahol this, valahol _this
van, tipikusan gondot okoz a kód áthelyezésnél)
obj.greetAll = function() {
var _this = this;
this.names.forEach(function() {
/* itt _this kell */ });
};
41. Megoldási lehetőségek: _this
• Használjunk mindenhol _this-t
• Minden metódus funkciójú függvényünket kezdjük
azzal, hogy meghatározzuk a _this -t.
• Konzisztens, de lusták vagyunk megtenni.
obj.greetAll = function() {
var _this = this;
_this.names.forEach(function() {
/* itt _this kell */ });
};
42. Megoldási lehetőségek: that
• Használjunk that-et és closure-okat
• Nem JavaScript-es szemléletű, de jól tömöríthető
function AllGreeter(greeting, names) {
var that = new Greeter(greeting); // !!!
that.greetAll = function() {
names.forEach(function(name) {
that.greet(name);
});
};
return that;
}
43. Megoldási lehetőségek: TypeScript, CoffeeScript
• Mint a demóban is látható volt, a JavaScript-re
épülő nyelvek segítségével nem szükséges olyan
nagy kódot írnunk, és JavaScript-es szemlélettel
programozhatunk.