Koje se metode mogu koristiti za definiranje klase u JavaScriptu i koje su njihove kompromisi?

Radije koristim OOP u velikim projektima, kao što je onaj na kojem radim. Moram stvoriti nekoliko klasa u JavaScriptu, ali ako se ne varam, postoji barem nekoliko načina za to. Kakva će biti sintaksa i zašto će se to raditi na taj način?

Želio bih izbjeći korištenje knjižnica trećih strana - barem prvo.
U potrazi za drugim odgovorima, pronašao sam članak Objektno-orijentirano programiranje s JavaScriptom, dio I: Nasljeđivanje - JavaScript Doc , koji raspravlja o objektno-orijentiranom programiranju u JavaScriptu.

633
23 дек. Karim postavljen 23. prosinca. 2008-12-23 02:07 '08 u 2:07 2008-12-23 02:07
@ 18 odgovora

Ovdje možete to učiniti bez korištenja vanjskih knjižnica:

 // Define a class like this function Person(name, gender){ // Add object properties like this this.name = name; this.gender = gender; } // Add methods like this. All Person objects will be able to invoke this Person.prototype.speak = function(){ alert("Howdy, my name is" + this.name); }; // Instantiate new objects with 'new' var person = new Person("Bob", "M"); // Invoke methods like this person.speak(); // alerts "Howdy, my name is Bob" 

Sada je pravi odgovor mnogo složeniji. Na primjer, u JavaScriptu nema takvih stvari kao što su klasa. JavaScript koristi shemu nasljeđivanja temeljenu na prototype .

Osim toga, postoje mnoge popularne JavaScript biblioteke koje imaju vlastiti stil približne funkcionalnosti klase u JavaScriptu. Morat ćete testirati barem Prototype i jQuery .

Određivanje koji je najbolji "odličan" je sjajan način za početak svetog rata sa Stack Overflowom. Ako krenete na veliki projekt s teškim JavaScript dizajnom, onda je svakako vrijedno istražiti popularnu knjižnicu i to učiniti na svoj način. Ja sam prototip, ali čini se da je Stack Overflow nagnut prema jQuery.

Budući da postoji samo jedan način da se to učini, bez ikakvih ovisnosti o vanjskim knjižnicama, kao što sam napisao, u velikoj mjeri.

691
23 дек. Odgovor daje Triptih 23 prosinca. 2008-12-23 02:16 '08 u 2:16 2008-12-23 02:16

Najbolji način definiranja klase u JavaScriptu je ne definirati klasu.

Ozbiljno.

Postoji nekoliko različitih opcija za orijentaciju objekta, od kojih su neke:

  • klasa OO (prvi put predstavio Smalltalk)
  • OO prototip (prvi put uveden od Self-a)
  • Multi OO (mislim da je prvi put uveo CommonLoops)
  • predikat OO (nema pojma)

A možda i drugi za koje ne znam.

border=0

JavaScript implementira OO prototip. U OO-u, na temelju prototipa, stvaraju se novi objekti kopiranjem drugih objekata (umjesto stvaranja instance iz predloška razreda), a metode žive izravno u objektima, a ne u klasama. Nasljeđivanje se vrši delegiranjem: ako objekt nema metodu ili svojstvo, ona se pregledava na njegovom prototipu (to jest, objektu s kojim je kloniran), zatim prototipu prototipa itd.

Drugim riječima: nema razreda.

JavaScript ima dobre postavke za ovaj model: konstruktori. Ne samo da možete stvarati objekte kopiranjem postojećih, već ih možete i izgraditi "iz zraka", da tako kažemo. Ako pozovete funkciju s new ključnom riječi, ova funkcija postaje konstruktor, a this ne pokazuje na trenutni objekt, već na novo stvoreno "prazno". Dakle, objekt možete prilagoditi na bilo koji način. Prema tome, JavaScript konstruktori mogu koristiti jednu od uloga klasa u tradicionalnom OO baziranom na klasi: poslužiti kao predložak ili plan za nove objekte.

Sada je JavaScript vrlo moćan jezik, tako da je vrlo lako implementirati OO sustav koji se temelji na klasi u JavaScriptu ako želite. Međutim, to biste trebali učiniti samo ako ga stvarno trebate, a ne samo zato što to Java radi.

204
23 дек. Odgovor daje Jörg W Mittag 23. prosinca. 2008-12-23 19:44 '08 u 19:44 2008-12-23 19:44

Razredi ES2015

U specifikaciji ES2015 možete koristiti sintaksu klase koja je samo šećer u odnosu na prototip.

podrškom za preglednik u ovom trenutku nije jako dobra (podržava gotovo svatko osim IE), ali sada možete koristiti ove funkcije uz pomoć transpiler kao Babel . 

sredstva

66
08 июня '15 в 7:46 2015-06-08 07:46 odgovor je dan Dale 08. lipnja '15. u 7:46 sati 2015-06-08 07:46

Radije koristim Daniel X. Moore {SUPER: SYSTEM} . To je disciplina koja pruža prednosti kao što su prave varijable instance, nasljeđivanje na temelju značajki, hijerarhije klasa i konfiguracijski parametri. Primjer u nastavku prikazuje upotrebu pravih varijabli instance, što je po mom mišljenju najveća prednost. Ako ne trebate varijable instance i ako ste zadovoljni samo javnim ili privatnim varijablama, vjerojatno postoje jednostavniji sustavi.

 function Person(I) { I = I || {}; Object.reverseMerge(I, { name: "McLovin", age: 25, homeState: "Hawaii" }); return { introduce: function() { return "Hi I'm " + I.name + " and I'm " + I.age; } }; } var fogel = Person({ age: "old enough" }); fogel.introduce(); // "Hi I'm McLovin and I'm old enough" 

Wow, ovo nije jako korisno za njega, ali pogledajte dodavanje podrazreda:

 function Ninja(I) { I = I || {}; Object.reverseMerge(I, { belt: "black" }); // Ninja is a subclass of person return Object.extend(Person(I), { greetChallenger: function() { return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you..."; } }); } var resig = Ninja({name: "John Resig"}); resig.introduce(); // "Hi I'm John Resig and I'm 25" 

Još jedna prednost je sposobnost imati modula i nasljeđivanje temeljeno na značajkama.

 // The Bindable module function Bindable() { var eventCallbacks = {}; return { bind: function(event, callback) { eventCallbacks[event] = eventCallbacks[event] || []; eventCallbacks[event].push(callback); }, trigger: function(event) { var callbacks = eventCallbacks[event]; if(callbacks  callbacks.length) { var self = this; callbacks.forEach(function(callback) { callback(self); }); } }, }; } 

Primjer postojanja klase osobe uključuje obvezujući modul.

 function Person(I) { I = I || {}; Object.reverseMerge(I, { name: "McLovin", age: 25, homeState: "Hawaii" }); var self = { introduce: function() { return "Hi I'm " + I.name + " and I'm " + I.age; } }; // Including the Bindable module Object.extend(self, Bindable()); return self; } var person = Person(); person.bind("eat", function() { alert(person.introduce() + " and I'm eating!"); }); person.trigger("eat"); // Blasts the alert! 

Objava: Ja sam Daniel X. Moore, a ovo je moja {SUPER: SYSTEM} . Ovo je najbolji način za definiranje klase u javascriptu.

55
17 сент. Odgovor je dan Daniel X Moore 17. rujna. 2010-09-17 01:14 '10 u 1:14 2010-09-17 01:14
 var Animal = function(options) { var name = options.name; var animal = {}; animal.getName = function() { return name; }; var somePrivateMethod = function() { }; return animal; }; // usage var cat = Animal({name: 'tiger'}); 
40
23 июля '09 в 7:46 2009-07-23 07:46 odgovor je dao liammclennan 23. srpnja '09 u 7:46 am 2009-07-23 07:46

U nastavku se nalaze načini stvaranja objekata u javascriptu koji sam do sada koristio.

Primjer 1:

 obj = new Object(); obj.name = 'test'; obj.prototype.sayHello = function() { console.log('Hello '+ this.name); } 

Primjer 2:

 obj = {}; obj.name = 'test'; obj.sayHello = function() { console.log('Hello '+ this.name); } obj.sayHello(); 

Primjer 3:

 var obj = function(nameParam) { this.name = nameParam; } obj.prototype.sayHello = function() { console.log('Hello '+ this.name); } 

Primjer 4: Stvarne prednosti Object.create (). pogledajte [ovaj link]

 var Obj = { init: function(nameParam) { this.name = nameParam; }, sayHello: function() { console.log('Hello '+ this.name); } }; var usrObj = Object.create(Obj); // <== one level of inheritance usrObj.init('Bob'); usrObj.sayHello(); 

Primjer 5 (prilagođeni objekt Crockford Object.create):

 Object.build = function(o) { var initArgs = Array.prototype.slice.call(arguments,1) function F() { if((typeof o.init === 'function')  initArgs.length) { o.init.apply(this,initArgs) } } F.prototype = o return new F() } MY_GLOBAL = {i: 1, nextId: function(){return this.i++}} // For example var userB = { init: function(nameParam) { this.id = MY_GLOBAL.nextId(); this.name = nameParam; }, sayHello: function() { console.log('Hello '+ this.name); } }; var bob = Object.build(userB, 'Bob'); // Different from your code bob.sayHello(); 

<h / "> Za spremanje odgovora ažurira se pomoću ES6 / ES2015

Klasa je definirana na sljedeći način:

 class Person { constructor(strName, numAge) { this.name = strName; this.age = numAge; } toString() { return '((Class::Person) named ' + this.name + '  of age ' + this.age + ')'; } } let objPerson = new Person("Bob",33); console.log(objPerson.toString()); 
24
04 марта '13 в 9:49 2013-03-04 09:49 odgovor je dao Amol M Kulkarni 04. ožujka 2013. u 9:49 2013-03-04 09:49

Mislim da biste trebali pročitati Douglas Crockford nasljeđivanje prototipova u JavaScriptu i klasično nasljeđivanje u JavaScriptu .

Primjeri s njegove stranice:

 Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; }; 

Efekt? To će vam omogućiti da na elegantniji način dodate metode:

 function Parenizor(value) { this.setValue(value); } Parenizor.method('setValue', function (value) { this.value = value; return this; }); 

Također preporučujem njegov video: Advanced JavaScript .

Na stranici možete pronaći više videa: http://javascript.crockford.com/ U knjizi Johna Reisiga možete pronaći mnogo primjera s web-lokacije Douglasa Crockfor-a.

23
23 дек. Odgovor je dan Jarek 23 dec. 2008-12-23 05:06 '08 u 5:06 2008-12-23 05:06

Zato što neću prihvatiti plan tvornice YUI / Crockford, i zato što volim držati sve bijesnim i proširivim, to je moja promjena:

 function Person(params) { this.name = params.name || defaultnamevalue; this.role = params.role || defaultrolevalue; if(typeof(this.speak)=='undefined') //guarantees one time prototyping { Person.prototype.speak = function() {}; } } var Robert = new Person({name:'Bob'}); 

gdje je u idealnom slučaju test tipa na nečemu sličnom prvom prototipu metode

15
29 дек. Odgovor je dan 29. prosinca. 2008-12-29 01:11 '09 u 1:11 2008-12-29 01:11

Ako ćete biti jednostavni, možete potpuno eliminirati "novu" ključnu riječ i jednostavno koristiti metode tvornice. Ponekad to preferiram jer koristim JSON za stvaranje objekata.

 function getSomeObj(var1, var2){ var obj = { instancevar1: var1, instancevar2: var2, someMethod: function(param) { //stuff; } }; return obj; } var myobj = getSomeObj("var1", "var2"); myobj.someMethod("bla"); 

Nisam siguran da je izvedba bila uspješna za velike objekte.

14
23 дек. Odgovor je dat Samu 23. prosinca. 2008-12-23 02:22 '08 u 2:22 am 2008-12-23 02:22
 var Student = (function () { function Student(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; this.fullname = firstname + " " + lastname; } Student.prototype.sayMyName = function () { return this.fullname; }; return Student; }()); var user = new Student("Jane", "User"); var user_fullname = user.sayMyName(); 

Kako TypeScript kompajlira klasu s konstruktorom u JavaScriptu.

11
15 марта '16 в 12:47 2016-03-15 12:47 odgovor je dat Mick 15. ožujka '16 u 12:47 2016-03-15 12:47

Vjerojatno ćete željeti stvoriti vrstu pomoću predloška Preklapanje:

  // Here is the constructor section. var myType = function () { var N = {}, // Enclosed (private) members are here. X = this; // Exposed (public) members are here. (function ENCLOSED_FIELDS() { N.toggle = false; N.text = ''; }()); (function EXPOSED_FIELDS() { X.count = 0; X.numbers = [1, 2, 3]; }()); // The properties below have access to the enclosed fields. // Careful with functions exposed within the closure of the // constructor, each new instance will have it own copy. (function EXPOSED_PROPERTIES_WITHIN_CONSTRUCTOR() { Object.defineProperty(X, 'toggle', { get: function () { var before = N.toggle; N.toggle = !N.toggle; return before; } }); Object.defineProperty(X, 'text', { get: function () { return N.text; }, set: function (value) { N.text = value; } }); }()); }; // Here is the prototype section. (function PROTOTYPE() { var P = myType.prototype; (function EXPOSED_PROPERTIES_WITHIN_PROTOTYPE() { Object.defineProperty(P, 'numberLength', { get: function () { return this.numbers.length; } }); }()); (function EXPOSED_METHODS() { P.incrementNumbersByCount = function () { var i; for (i = 0; i < this.numbers.length; i++) { this.numbers[i] += this.count; } }; P.tweak = function () { if (this.toggle) { this.count++; } this.text = 'tweaked'; }; }()); }()); 

Ovaj kod će vam dati vrstu pod nazivom myType . Imat će unutarnja privatna polja koja se nazivaju preklop i tekst . On će također imati te otvorene sudionike: brojna i brojčana polja; svojstva preklapaju , tekst i brojLength ; metode incrementNumbersByCount i prilagoditi .

Ovdje je detaljno opisan sklopivi uzorak: Javascript Folding Pattern

9
07 апр. Odgovor dao Chris Nash 07. travnja 2013-04-07 03:43 '13 u 3:43 2013-04-07 03:43

Jednostavan način je:

 function Foo(a) { var that=this; function privateMethod() { .. } // public methods that.add = function(b) { return a + b; }; that.avg = function(b) { return that.add(b) / 2; // calling another public method }; } var x = new Foo(10); alert(x.add(2)); // 12 alert(x.avg(20)); // 15 

Razlog za this da se this može vezati za nešto drugo ako metodu date kao rukovatelj događajima, tako da spremite vrijednost tijekom stvaranja instance i koristite je kasnije.

Edit: ovo definitivno nije najbolji način, samo jednostavan način. Također čekam dobre odgovore!

8
23 дек. odgovor se daje orip 23 dec. 2008-12-23 02:33 '08 u 2:33 am 2008-12-23 02:33

Golf kod za @liammclennan odgovor .

3
16 авг. odgovor dan tponthieux 16 kol. 2016-08-16 02:42 '16 u 2:42 am 2016-08-16 02:42

Objektno orijentirane klase s nasljeđivanjem

 var baseObject = { // Replication / Constructor function new : function(){ return Object.create(this); }, aProperty : null, aMethod : function(param){ alert("Heres your " + param + "!"); }, } newObject = baseObject.new(); newObject.aProperty = "Hello"; anotherObject = Object.create(baseObject); anotherObject.aProperty = "There"; console.log(newObject.aProperty) // "Hello" console.log(anotherObject.aProperty) // "There" console.log(baseObject.aProperty) // null 

Jednostavno, slatko i djelo.

2
02 февр. odgovor je dat Ulad Kasach 02 Feb. 2016-02-02 19:36 '16 u 19:36 2016-02-02 19:36

MooTools (Moji objektno orijentirani alati) usredotočuje se na tu ideju. Možete čak i proširiti i implementirati sa nasljeđivanjem.

Kada ga svladate, on čini smiješno višekratnu upotrebu, moćan javascript.

2
30 мая '09 в 5:22 2009-05-30 05:22 odgovor je dao Ryan Florence 30. svibnja u 5:22 2009-05-30 05:22

Na temelju Triptych primjera, to može biti još jednostavnije:

  // Define a class and instantiate it var ThePerson = new function Person(name, gender) { // Add class data members this.name = name; this.gender = gender; // Add class methods this.hello = function () { alert('Hello, this is ' + this.name); } }("Bob", "M"); // this instantiates the 'new' object // Use the object ThePerson.hello(); // alerts "Hello, this is Bob" 

Ovo stvara samo jednu instancu objekta, ali je još uvijek korisno ako želite u kapsulirati hrpu imena varijabli i metoda u klasi. Obično ne postoje argumenti "Bob, M" za konstruktora, na primjer, ako su metode sustavni pozivi s vlastitim podacima, kao što su baza podataka ili mreža.

Još uvijek sam previše upoznat s JS-om da bih shvatio zašto ne koristi prototype .

0
23 авг. Odgovor dao Roland 23. kolovoza. 2017-08-23 11:39 '17 u 11:39 2017-08-23 11:39

baza

 function Base(kind) { this.kind = kind; } 

klasa

 // Shared var var _greeting; (function _init() { Class.prototype = new Base(); Class.prototype.constructor = Class; Class.prototype.log = function() { _log.apply(this, arguments); } _greeting = "Good afternoon!"; })(); function Class(name, kind) { Base.call(this, kind); this.name = name; } // Shared function function _log() { console.log(_greeting + " Me name is " + this.name + " and I'm a " + this.kind); } 

posljedica

 var c = new Class("Joe", "Object"); c.log(); // "Good afternoon! Me name is Joe and I'm a Object" 
0
18 июля '17 в 14:22 2017-07-18 14:22 odgovor daje Mikael Dúi Bolinder 18. srpnja '17. u 14:22 sati 2017-07-18 14:22

JavaScript je objektno orijentiran , ali se radikalno razlikuje od drugih OOP-ova , kao što su Java, C # ili C ++. Ne pokušavajte to shvatiti. Spustite staro znanje i krenite iznova. JavaScript treba drugačiji način razmišljanja.

Savjetovao bih vam da dobijete dobar vodič ili nešto o tome. Ja sam pronašao ExtJS Tutoriali najbolje za mene, iako nisam koristiti okvir prije ili nakon čitanja. Ali to daje dobro objašnjenje onoga što je u svijetu JavaScripta. Nažalost, izgleda da je ovaj sadržaj izbrisan. Ovdje je link na copy.org archive.org umjesto. Radi danas.: P

0
23 дек. odgovor je dao Vilx- 23 dec. 2008-12-23 02:32 '08 u 2:32 2008-12-23 02:32

Ostala pitanja o oznakama ili postavi pitanje