Konstruktory w obiektach JavaScript

Odpowiedzi:

408

Korzystanie z prototypów:

function Box(color) // Constructor
{
    this.color = color;
}

Box.prototype.getColor = function()
{
    return this.color;
};

Ukrywanie „koloru” (nieco przypomina prywatną zmienną członka):

function Box(col)
{
   var color = col;

   this.getColor = function()
   {
       return color;
   };
}

Stosowanie:

var blueBox = new Box("blue");
alert(blueBox.getColor()); // will alert blue

var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green
Nacięcie
źródło
3
@ BorisB, tak robisz - określa kolor i getColor na obiekcie Box, w przeciwnym razie przypisujesz zmienne w zwykłym zakresie.
Nick
4
@Jeach tak to robi. Podałem alternatywny fragment, który ukrywa color. Sugeruję, że używasz w dużej mierze zależy od osobistych preferencji (ochrona kontra prostota)
Nick
6
@CamiloMartin Chociaż nie zawsze jest to konieczne, uczynienie zmiennej „prywatną” (lub w tym przypadku nienazwalną) może być użytecznym sposobem, aby zapobiec uzależnieniu kodu zewnętrznego od szczegółów implementacyjnych twojej klasy. Nawet samo wskazanie, które elementy klasy są publiczne / prywatne, może być przydatne dla użytkowników zewnętrznych.
Nick
49
vartworzy zmienną prywatną. thistworzy zmienną publiczną
EhevuTov
3
@AlanKis (Przynajmniej w niektórych silnikach JavaScript) ślad stosu w anonimowym przypadku funkcji nawet nie wspomina Foo, podczas gdy w drugim przypadku będzie wiedział, że Foojest wywoływany. Bardzo pomocne przy debugowaniu.
Joachim Isaksson
248

Oto szablon, którego czasami używam do zachowania podobnego do OOP w JavaScript. Jak widać, można symulować członków prywatnych (zarówno statycznych, jak i instancji) przy użyciu zamknięć. To, new MyClass()co zwróci, to obiekt z jedynie właściwościami przypisanymi do thisobiektu i prototypeobiektu „klasy”.

var MyClass = (function () {
    // private static
    var nextId = 1;

    // constructor
    var cls = function () {
        // private
        var id = nextId++;
        var name = 'Unknown';

        // public (this instance only)
        this.get_id = function () { return id; };

        this.get_name = function () { return name; };
        this.set_name = function (value) {
            if (typeof value != 'string')
                throw 'Name must be a string';
            if (value.length < 2 || value.length > 20)
                throw 'Name must be 2-20 characters long.';
            name = value;
        };
    };

    // public static
    cls.get_nextId = function () {
        return nextId;
    };

    // public (shared across instances)
    cls.prototype = {
        announce: function () {
            alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
                  'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
        }
    };

    return cls;
})();

Zapytano mnie o dziedziczenie przy użyciu tego wzorca, więc oto:

// It's a good idea to have a utility class to wire up inheritance.
function inherit(cls, superCls) {
    // We use an intermediary empty constructor to create an
    // inheritance chain, because using the super class' constructor
    // might have side effects.
    var construct = function () {};
    construct.prototype = superCls.prototype;
    cls.prototype = new construct;
    cls.prototype.constructor = cls;
    cls.super = superCls;
}

var MyChildClass = (function () {
    // constructor
    var cls = function (surName) {
        // Call super constructor on this instance (any arguments
        // to the constructor would go after "this" in call(…)).
        this.constructor.super.call(this);

        // Shadowing instance properties is a little bit less
        // intuitive, but can be done:
        var getName = this.get_name;

        // public (this instance only)
        this.get_name = function () {
            return getName.call(this) + ' ' + surName;
        };
    };
    inherit(cls, MyClass); // <-- important!

    return cls;
})();

I przykład wykorzystania tego wszystkiego:

var bob = new MyClass();
bob.set_name('Bob');
bob.announce(); // id is 1, name shows as "Bob"

var john = new MyChildClass('Doe');
john.set_name('John');
john.announce(); // id is 2, name shows as "John Doe"

alert(john instanceof MyClass); // true

Jak widać, klasy poprawnie komunikują się ze sobą (współdzielą statyczny identyfikator z MyClass, announcemetoda używa poprawnej get_namemetody itp.)

Należy zwrócić uwagę na potrzebę ukrywania właściwości instancji. W rzeczywistości można sprawić, aby inheritfunkcja przechodziła przez wszystkie właściwości instancji (za pomocą hasOwnProperty), które są funkcjami, i dodawała super_<method name>właściwość automatycznie . Pozwoliłoby to zadzwonić this.super_get_name()zamiast przechowywać go w wartości tymczasowej i nazwać go związanym za pomocą call.

W przypadku metod na prototypie nie musisz się jednak przejmować powyższym, jeśli chcesz uzyskać dostęp do metod prototypowych superklasy, możesz po prostu zadzwonić this.constructor.super.prototype.methodName. Jeśli chcesz, aby było mniej gadatliwe, możesz oczywiście dodać właściwości wygody. :)

Blixt
źródło
7
Tylko uwaga na temat cls.prototypeczęści: „współdzielone między instancjami” służy tylko do odczytu wartości (wywołanie announce). Jeśli ustawisz myClassInstance.announceinną wartość, tworzy ona nową właściwość w myClassInstance, więc ma zastosowanie tylko do tego obiektu, a nie do innych instancji klasy. Przypisanie do MyClass.prototype.announcewpłynie jednak na wszystkie instancje.
Matthew Crumley,
1
Nie ma problemu, cieszę się, że mogłem pomóc! :)
Blixt,
2
Dziękuję Ci! Bardzo mi się podobało! Czy możesz pokazać przykład dziedziczenia klas w tym podejściu?
Dmitrij Golubev
2
@DmitrijGolubev, Brad Dwyer i Nathan C. Tresch: Dodałem dziedziczenie, ale robi się to dość skomplikowane, więc zwykle radziłbym ci iść z prostszym rozwiązaniem, chyba że potrzebujesz tak trudnego dziedziczenia w JavaScript (co jest tak naprawdę tylko język prototypowy).
Blixt
1
@ guiomie Jest to „publiczna statyczna” metoda, więc wywołałbyś ją na funkcji konstruktora („klasie”), a nie na instancji:MyClass.get_nextId()
Blixt
166

Wydaje mi się, że większość z was podaje przykłady programów pobierających i ustawiających, a nie konstruktorów, tj. Http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming) .

lunched-dan był bliżej, ale przykład nie działał w jsFiddle.

W tym przykładzie tworzona jest funkcja prywatnego konstruktora, która działa tylko podczas tworzenia obiektu.

var color = 'black';

function Box()
{
   // private property
   var color = '';

   // private constructor 
   var __construct = function() {
       alert("Object Created.");
       color = 'green';
   }()

   // getter
   this.getColor = function() {
       return color;
   }

   // setter
   this.setColor = function(data) {
       color = data;
   }

}

var b = new Box();

alert(b.getColor()); // should be green

b.setColor('orange');

alert(b.getColor()); // should be orange

alert(color); // should be black

Jeśli chcesz przypisać właściwości publiczne, konstruktor można zdefiniować jako taki:

var color = 'black';

function Box()
{
   // public property
   this.color = '';

   // private constructor 
   var __construct = function(that) {
       alert("Object Created.");
       that.color = 'green';
   }(this)

   // getter
   this.getColor = function() {
       return this.color;
   }

   // setter
   this.setColor = function(color) {
       this.color = color;
   }

}

var b = new Box();

alert(b.getColor()); // should be green

b.setColor('orange'); 

alert(b.getColor()); // should be orange

alert(color); // should be black
Jon
źródło
45
Jak to nie jest odpowiedź nr 1? Tylko Jon stworzył konstruktor z parametrami.
Rap
1
Czy jest jakiś sposób, aby uzyskać przykład dziedziczenia za pomocą tego paradygmatu dla konstruktorów?
Nathan C. Tresch
1
Przykład konstruktora @Rap Jona nie ma parametrów, ponieważ jest Box()funkcją :). Ale ten przykład, jak również przykłady w innych odpowiedziach, można łatwo rozszerzyć na parametry.
Alexander Stepaniuk
2
@AndersonGreen możesz dodać parametr do Boxa, a następnie przekazać go do prywatnego konstruktora jako parametr funkcji.
Gautham C.
1
Nie ma potrzeby „prywatnych konstruktorów”. Po prostu wykonaj swoją konstrukcję w Boxfunkcji i możesz zacząć (jest to nadal „prywatny”). „Prywatne” w Javascript oznacza po prostu dostępne w zakresie leksykalnym; nie trzeba przypisywać członków. Dodatkowo: ten kod jest nieprawidłowy. Tworzy __constructzmienną globalną , co jest dość złe. varnależy stosować w celu ograniczenia zakresu __construct.
mattbasta
23

Jaki jest więc sens własności „konstruktora”? Nie możesz dowiedzieć się, gdzie może być przydatne, jakieś pomysły?

Celem właściwości konstruktora jest zapewnienie sposobu udawania, że ​​JavaScript ma klasy. Jedną z rzeczy, których nie możesz zrobić, jest zmiana konstruktora obiektu po jego utworzeniu. To skomplikowane.

Kilka lat temu napisałem dość obszerny artykuł: http://joost.zeekat.nl/constructors-consisted-mildly-confusing.html

Joost Diepenmaat
źródło
Chodzi o to, aby użyć słowa kluczowego „new”. „d = new Drofto ()” tworzy pusty obiekt i uruchamia funkcję Drofto ze wspomnianym nowym obiektem ograniczonym jako „ten”. Funkcja Drofto może dowolnie zwracać wszystko, ale zwyczajowo zwraca się coś, co można uznać za członka klasy Drofto.
Juan Lanus,
16

Przykład tutaj: http://jsfiddle.net/FZ5nC/

Wypróbuj ten szablon:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
  v1: null
 ,v2: null
 ,f1: function Name_Space_ClassName_f1(){}
}

//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;

//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>

Musisz dostosować przestrzeń nazw, jeśli definiujesz klasę statyczną:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>

Przykładowa klasa:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
    this.Width = width;
    this.Height = height;
    this.Color = color;
}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
  Width: null
 ,Height: null
 ,Color: null
 ,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
    var canvas = document.getElementById(canvasId);
    var context = canvas.getContext("2d");
    context.fillStyle = this.Color;
    context.fillRect(x, y, this.Width, this.Height);
 }
}

//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;

//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
    return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
    return new Shape.Rectangle(50,25,'#ff0000');
}
</script>

Przykładowa instancja:

<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");

var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);

var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);

Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>

Funkcje powiadomień są zdefiniowane jako AB = funkcja A_B (). Ma to na celu ułatwienie debugowania skryptu. Otwórz panel Inspect Element w Chrome, uruchom ten skrypt i rozwiń ślad debugowania:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};

//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
    A.Func.That.Does.Not.Exist();
}

Fail.Test();
</script>
bitlather
źródło
Dodano przykład. Dodano także informacje o poprawianiu wyników debugowania.
bitlather
1
Prawdopodobnie dlatego, że dodaje niepotrzebnego poziomu złożoności do problemu. Trudno znaleźć odpowiedź w swoim poście ze względu na pedantyczne odstępy między nazwami i deklarację klasy statycznej. Nie zrozum mnie źle, to dobra informacja, ale z pewnością jest bardziej myląca niż pomocna, jeśli próbujesz dostać się do drzwi w zrozumieniu. Jestem w połowie kompetentny w JS i ledwo rozumiem, co tu robisz, ani dlaczego ma to znaczenie dla „Jak zbudować?”
Bmo
1
Dzięki za wgląd, Bmo. To był długi post, ale to dlatego, że nie rozumiem użycia konstruktora, jeśli nie jest on powiązany z dobrze zdefiniowanym obiektem i implementacją klasy statycznej. Ucząc się C ++ lub Java, musisz nauczyć się implementować klasy wraz z implementacją konstruktorów. Web dev stał się znacznie przyjemniejszy, odkąd natknąłem się na tę metodę pisania javascript, i po prostu chciałem się nią podzielić. Przeniosłem skrzypce na górę, aby łatwiej było je znaleźć. Mam nadzieję, że rozwiąże to wszelkie nieporozumienia.
bitlather
1
@Bmo Czy jesteś poważny, że dwie linie dotyczące przestrzeni nazw trudno znaleźć konstruktora dokładnie poniżej, szczególnie biorąc pod uwagę komentarz Konstruktor - MUSI BYĆ NA GÓRZE PLIKU? Podanie przykładu z przestrzenią nazw jest bardzo mile widziane, społeczność deweloperów javascript ślepo ignoruje przestrzenie nazw, powodując trudne do znalezienia błędy, gdy nazwy się zderzają. To smutne, że deweloperzy js myślą, że jeśli skopiują fragment tekstu z posta w Internecie i zrobią coś podobnego do tego, czego potrzebują, ich praca jest kompletna.
user3285954
1
Głównym problemem związanym z js i tworzeniem stron internetowych jest to, że większość deweloperów ignoruje wszystkie praktyki tworzone przez przemysł od ponad 50 lat i myśli, że jeśli są w stanie wywołać wywołanie ajax, to oni są królem. Przykro mi, że tyle lat zajęło mi użycie dobrze znanych wzorców i praktyk w javascript.
user3285954
10

To jest konstruktor:

function MyClass() {}

Kiedy to zrobisz

var myObj = new MyClass();

MyClass jest wykonywany i zwracany jest nowy obiekt tej klasy.

Satish N Ramteare
źródło
1
Aby wyjaśnić, co to oznacza, znajduje się na szczycie klasy, możesz powiedzieć, alert(valuePassedInAsArgument);że będzie to działać raz dla każdej instancji, więc cała klasa jest konstruktorem.
Martin Lyne
new object is returned of that class- czy to nie bardziej, że zwracany jest nowy obiekt tej funkcji?
Don Cheadle
w funkcjach javascript są obiekty
Leo
8

Uważam ten samouczek za bardzo przydatny. Takie podejście jest stosowane przez większość wtyczek jQuery.

http://www.htmlgoodies.com/html5/tutorials/create-an-object-oriented-javascript-class-constructor.html#fbid=OVYAQL_TDpK

var Class = function(methods) {   
    var klass = function() {    
        this.initialize.apply(this, arguments);          
    };  

    for (var property in methods) { 
       klass.prototype[property] = methods[property];
    }

    if (!klass.prototype.initialize) klass.prototype.initialize = function(){};      

    return klass;    
};

Teraz ,

var Person = Class({ 
    initialize: function(name, age) {
        this.name = name;
        this.age  = age;
    },
    toString: function() {
        return "My name is "+this.name+" and I am "+this.age+" years old.";
    }
}); 

var alice = new Person('Alice', 26);
alert(alice.name); //displays "Alice"
alert(alice.age); //displays "26"
alert(alice.toString()); //displays "My name is Alice and I am 26 years old" in most browsers.
//IE 8 and below display the Object's toString() instead! "[Object object]"
anasanjaria
źródło
10
Kulę się, ilekroć widzę ludzi używającychklass
Madbreaks
8

Ten wzór mi dobrze służył. Za pomocą tego wzorca tworzysz klasy w osobnych plikach, ładujesz je do swojej ogólnej aplikacji „w razie potrzeby”.

// Namespace
// (Creating new if not instantiated yet, otherwise, use existing and just add to it)
var myApp = myApp || {};

// "Package" 
// Similar to how you would establish a package in other languages
(function() {

// "Class"
var MyClass = function(params) {
    this.initialize(params);
}

    // "Private Static" vars 
    //    - Only accessible to functions in this class.
    //    - Doesn't get wiped out when we create a new instance.
    var countInstances = 0;
    var allInstances = [];

    // "Private Static" functions 
    //    - Same as above, but it's a function accessible 
    //      only to other functions in this class.
    function doSomething(){
    }

    // "Public Static" vars
    //    - Everyone has access.
    //    - Doesn't get wiped out when we create a new instance.
    MyClass.counter = 0;

    // "Public Static" functions
    //    - Same as above, but anyone can call this "static method".
    //    - Kinda like a singleton class situation.
    MyClass.foobar = function(){
    }

    // Public properties and methods are built into the "prototype"
    //    - This is how each instance can become unique unto itself.
    //    - Establishing "p" as "local" (Static Private) variable 
    //      simply so we don't have to keep typing "MyClass.prototype" 
    //      for each property and function.
var p = MyClass.prototype;

    // "Public" vars
    p.id = null;
    p.firstname = null;
    p.lastname = null;

    // "Private" vars
    //    - Only used by "this" instance.
    //    - There isn't "true" privacy for each 
    //      instance so we have to fake it. 
    //    - By tradition, we indicate "privacy"  
    //      by prefixing it with an underscore. 
    //    - So technically, anyone can access, but we simply 
    //      don't tell anyone about it (e.g. in your API)
    //      so no one knows about it :)
    p._foo = null;

    p.initialize = function(params){
        this.id = MyClass.counter++;
        this.firstname = params.firstname;
        this.lastname = params.lastname;
        MyClass.counter++;
        countInstances++;
        allInstances.push(this);
    }

    p.doAlert = function(theMessage){
        alert(this.firstname + " " + this.lastname + " said: " + theMessage + ". My id:" + this.id + ".  Total People:" + countInstances + ". First Person:" + allInstances[0].firstname + " " + allInstances[0].lastname);
    }


// Assign class to app
myApp.MyClass = MyClass;

// Close the "Package"
}());

// Usage example:
var bob = new myApp.MyClass({   firstname   :   "bob",
                                lastname    :   "er"
                            });

bob.doAlert("hello there");
kok
źródło
Są to zmienne instancji, ale mają one dostęp „publiczny”, a nie „prywatny” jak w C ++ lub Javie.
Potatoswatter
Jak poszedłbyś do stworzenia zmiennej prywatnej (w klasycznym sensie), która jest relatywna do instancji, ale nie jest wspólna dla wszystkich instancji?
Bob
Zobacz stronę Douglasa Crockforda , on jest jednym z projektantów języków i najważniejszym autorytetem. Nie zawsze podążam za jego wzorcami, ale generalnie zmienna prywatna jest lokalna varw konstruktorze (lub argumencie funkcji lub w funkcji podobnej do konstruktora).
Potatoswatter
Dzięki za wskazówkę ... następująca strona wyjaśnia, czego szukałem: javascript.crockford.com/private.html
Bob
Och, przepraszam, że nie testowałem linku: P
Potatoswatter
8

Tak, możesz zdefiniować konstruktor w deklaracji klasy w następujący sposób:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
Bruno
źródło
dla vaersion IE> 12
zloctb
1
To jedyna faktyczna odpowiedź na pytanie. : /
MarcD
6

Myślę, że opublikuję to, co robię z zamknięciem javascript, ponieważ nikt jeszcze nie używa zamknięcia.

var user = function(id) {
  // private properties & methods goes here.
  var someValue;
  function doSomething(data) {
    someValue = data;
  };

  // constructor goes here.
  if (!id) return null;

  // public properties & methods goes here.
  return {
    id: id,
    method: function(params) {
      doSomething(params);
    }
  };
};

Komentarze i sugestie dotyczące tego rozwiązania są mile widziane. :)

Hendra Uzia
źródło
1
Kilka komentarzy: 1) instrukcja jeśli (! Id) nie jest bezpieczna, wartości takie jak 0 lub fałsz spowodują, że będzie ona oceniała wartość true i zwróci wartość null. Zgaduję, że chcesz sprawdzić, czy jest niezdefiniowany lub zerowy, w takim przypadku lepiej byłoby === null i === niezdefiniowane. 2) To bardziej przypomina wzorzec modułu ( odpowiednio Odpowiednikodod.com/2010/3/JavaScript-Module-Pattern-In-Depth ) w porównaniu z konstruktorem, różnica polega na tym, że moduł zwraca obiekt z funkcji, podczas gdy konstruktor tworzy obiekt, gdy w połączeniu z nowym słowem kluczowym, w takim przypadku należy ustawić wartości „to” zamiast obiektu.
Bogaty
4

Korzystając z powyższej próbki Nicka, możesz utworzyć konstruktor dla obiektów bez parametrów, używając instrukcji return jako ostatniej instrukcji w definicji obiektu. Zwróć swoją funkcję konstruktora jak poniżej, a będzie ona uruchamiała kod w __construct za każdym razem, gdy tworzysz obiekt:

function Box()
{
   var __construct = function() {
       alert("Object Created.");
       this.color = 'green';
   }

  this.color = '';

   this.getColor = function() {
       return this.color;
   }

   __construct();
}

var b = new Box();
Dan Power
źródło
1
Nie zwracasz funkcji konstruktora, tylko ją wywołujesz.
David Conrad,
Jeśli spróbujesz użyć this.getColor();linii powyżej, alert("Object Created.");nic nie zostanie ostrzeżone. Wystąpi błąd w rodzaju „getColor nie jest zdefiniowany”. Jeśli chcesz, aby konstrukcja mogła wywoływać inne metody w obiekcie, musisz zdefiniować ją po wszystkich innych metodach. Więc zamiast wywoływać __construct();ostatnią linię, po prostu zdefiniuj konstrukt tam i wstaw ()po nim, aby wymusić automatyczne wykonanie.
thinsoldier
Korekta. Dodanie ()na końcu definicji __construct nadal powodowało błąd. Musiałem wywołać __construct();własną linię, tak jak w oryginalnym kodzie, aby uniknąć błędu.
thinsoldier
4

Może stało się to trochę prostsze, ale poniżej przedstawiłem to, co wymyśliłem w 2017 roku:

class obj {
  constructor(in_shape, in_color){
    this.shape = in_shape;
    this.color = in_color;
  }

  getInfo(){
    return this.shape + ' and ' + this.color;
  }
  setShape(in_shape){
    this.shape = in_shape;
  }
  setColor(in_color){
    this.color = in_color;
  }
}

Korzystając z powyższej klasy, mam następujące elementy:

var newobj = new obj('square', 'blue');

//Here, we expect to see 'square and blue'
console.log(newobj.getInfo()); 

newobj.setColor('white');
newobj.setShape('sphere');

//Since we've set new color and shape, we expect the following: 'sphere and white'
console.log(newobj.getInfo());

Jak widać, konstruktor przyjmuje dwa parametry, a my ustawiamy właściwości obiektu. Zmieniamy również kolor i kształt obiektu za pomocą setterfunkcji i udowadniamy, że jego zmiana pozostała po wywołaniu getInfo()po tych zmianach.

Trochę za późno, ale mam nadzieję, że to pomoże. Przetestowałem to za pomocą mochatestów jednostkowych i działa dobrze.

Chim Chimz
źródło
3

Robią to, jeśli używasz Typescript - open source od MicroSoft :-)

class BankAccount {
 balance: number;
 constructor(initially: number) {
 this.balance = initially;
 }
 deposit(credit: number) {
 this.balance += credit;
 return this.balance;
 }
}

Maszynopis pozwala „fałszować” konstrukcje OO, które są kompilowane w konstrukcje javascript. Jeśli zaczynasz duży projekt, możesz zaoszczędzić dużo czasu i właśnie osiągnął wersję milestone 1.0.

http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf

Powyższy kod zostaje „skompilowany” w celu:

var BankAccount = (function () {
    function BankAccount(initially) {
        this.balance = initially;
    }
    BankAccount.prototype.deposit = function (credit) {
        this.balance += credit;
        return this.balance;
    };
    return BankAccount;
})();
Simon_Weaver
źródło
Pracuję nad dużym projektem i staram się przekonać ludzi, że TypeScript da nam szansę. Zobaczymy jak to będzie.
wootscootinboogie
@wootscootinboogie W ciągu jednego dnia (kończąc się teraz o 5.30) mam już dość daleko i całkiem wygodnie. Zdecydowanie polecam przeczytać specyfikację i chociaż możesz pominąć połowę prawdziwych drobiazgów, robisz sobie przysługę, czytając ją przynajmniej raz. filmy tego faceta są doskonałe youtube.com/user/basaratali/videos . powodzenia)
Simon_Weaver
1

W JavaScript typ wywołania określa zachowanie funkcji:

  • Bezpośrednie wywołanie func()
  • Wywołanie metody na obiekcie obj.func()
  • Wywołanie konstruktoranew func()
  • Pośrednie wywołanie func.call()lubfunc.apply()

Funkcja jest wywoływana jako konstruktor podczas wywoływania za pomocą newoperatora:

function Cat(name) {
   this.name = name;
}
Cat.prototype.getName = function() {
   return this.name;
}

var myCat = new Cat('Sweet'); // Cat function invoked as a constructor

Każda instancja lub obiekt prototypowy w JavaScript ma właściwość constructor, która odnosi się do funkcji konstruktora.

Cat.prototype.constructor === Cat // => true
myCat.constructor         === Cat // => true

Sprawdź ten post na temat właściwości konstruktora.

Dmitri Pavlutin
źródło
0

Korzystając z doskonałego szablonu Blixta z góry, dowiedziałem się, że nie działa dobrze z dziedziczeniem wielopoziomowym (MyGrandChildClass rozszerzającym MyChildClass rozszerzającym MyClass) - cyklicznie przywoływanie konstruktora pierwszego rodzica w kółko. Oto proste obejście - jeśli potrzebujesz dziedziczenia wielopoziomowego, zamiast this.constructor.super.call(this, surName);korzystać chainSuper(this).call(this, surName);z funkcji łańcucha zdefiniowanej w ten sposób:

function chainSuper(cls) {
  if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
  var depth = cls.__depth;
  var sup = cls.constructor.super;
  while (depth > 1) {
    if (sup.super != undefined) sup = sup.super;
    depth--;
  }
  return sup;
}
Jan
źródło
0

http://www.jsoops.net/ jest całkiem dobry dla oop w Js. Jeśli zapewnia prywatną, chronioną, publiczną zmienną i funkcję, a także funkcję dziedziczenia. Przykładowy kod:

var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public

    pri.className = "I am A ";

    this.init = function (var1)// constructor
    {
        pri.className += var1;
    }

    pub.getData = function ()
    {
        return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
        + ", ID=" + pro.getClassId() + ")";
    }

    pri.getClassName = function () { return pri.className; }
    pro.getClassName = function () { return pri.className; }
    pro.getClassId = function () { return 1; }
});

var newA = new ClassA("Class");

//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)

//***You can not access constructor, private and protected function
console.log(typeof (newA.init));            // undefined
console.log(typeof (newA.className));       // undefined
console.log(typeof (newA.pro));             // undefined
console.log(typeof (newA.getClassName));    // undefined
użytkownik1624059
źródło
0

żeby zaoferować trochę różnorodności. ds.oop to dobry sposób na deklarowanie klas za pomocą konstruktorów w javascript. Obsługuje każdy możliwy typ dziedziczenia (w tym 1 typ, który nie obsługuje nawet c #), a także interfejsy, co jest miłe.

var Color = ds.make.class({
    type: 'Color',
    constructor: function (r,g,b) { 
        this.r = r;                     /* now r,g, and b are available to   */
        this.g = g;                     /* other methods in the Color class  */
        this.b = b;                     
    }
});
var red = new Color(255,0,0);   // using the new keyword to instantiate the class
dss
źródło
0

Tutaj musimy zauważyć jeden punkt w skrypcie java, jest to język bezklasowy, jednak możemy to osiągnąć za pomocą funkcji w skrypcie java. Najczęstszym sposobem osiągnięcia tego celu jest utworzenie funkcji w skrypcie Java i użycie nowego słowa kluczowego do utworzenia obiektu oraz użycie tego słowa kluczowego do zdefiniowania właściwości i metod. Poniżej znajduje się przykład.

// Function constructor

   var calculator=function(num1 ,num2){
   this.name="This is function constructor";
   this.mulFunc=function(){
      return num1*num2
   };

};

var objCal=new calculator(10,10);// This is a constructor in java script
alert(objCal.mulFunc());// method call
alert(objCal.name);// property call

//Constructors With Prototypes

var calculator=function(){
   this.name="Constructors With Prototypes";
};

calculator.prototype.mulFunc=function(num1 ,num2){
 return num1*num2;
};
var objCal=new calculator();// This is a constructor in java script
alert(objCal.mulFunc(10,10));// method call
alert(objCal.name); // property call
Sheo Dayal Singh
źródło
-2

W większości przypadków musisz jakoś zadeklarować właściwość, której potrzebujesz, zanim będziesz mógł wywołać metodę przekazującą te informacje. Jeśli nie musisz początkowo ustawiać właściwości, możesz po prostu wywołać metodę w obiekcie w ten sposób. Prawdopodobnie nie jest to najpiękniejszy sposób na zrobienie tego, ale nadal działa.

var objectA = {
    color: ''; 
    callColor : function(){
        console.log(this.color);
    }
    this.callColor(); 
}
var newObject = new objectA(); 
Kontener kodowany
źródło