Конструктори в об’єктах JavaScript


Відповіді:


408

Використання прототипів:

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

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

Приховування "кольору" (дещо нагадує змінну приватного члена):

function Box(col)
{
   var color = col;

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

Використання:

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

var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green

3
@BorisB, так, ви робите - це визначає колір і getColor на об'єкті Box, інакше ви призначаєте змінні у звичайній області застосування.
Нік

4
@Jeach так. Я надав альтернативний фрагмент, який ховається color. Я б запропонував, який ви використовуєте, значною мірою залежить від особистих уподобань (захист проти простоти)
Нік

6
@CamiloMartin Хоча це не завжди необхідно, зробити змінну "приватною" (або в цьому випадку неіменною) може бути корисним способом запобігання зовнішньому коду, що стає залежним від деталей реалізації вашого класу. Навіть лише зазначення того, які елементи класу є державними / приватними, може бути корисним зовнішнім користувачам.
Нік

49
varробить приватну змінну. thisробить публічну змінну
EhevuTov

3
@AlanKis (Принаймні в деяких двигунах Javascript) слід стека у випадку анонімної функції навіть не згадується Foo, тоді як в останньому випадку він буде знати, що його Fooвикликають. Дуже корисно для налагодження.
Йоахім Ісакссон

248

Ось шаблон, який я іноді використовую для поведінки, подібної до OOP в JavaScript. Як бачите, ви можете імітувати приватні (як статичні, так і екземплярні) члени за допомогою закриття. Що new MyClass()повернеться - це об'єкт, у якому лише властивості, призначені thisоб'єкту, і в prototypeоб'єкті "класу".

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;
})();

Мене запитали про спадкування за цією схемою, тож ось:

// 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;
})();

І приклад, щоб все це використовувати:

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

Як бачимо, класи правильно взаємодіють між собою (вони поділяють статичний ідентифікатор MyClass, announceметод використовує правильний get_nameметод тощо)

Варто зазначити одне, що потрібно відтінити властивості примірника. Ви можете фактично змусити inheritфункцію пройти всі властивості примірника (використовуючи hasOwnProperty), які є функціями, і автоматично додати super_<method name>властивість. Це дозволить вам зателефонувати this.super_get_name()замість того, щоб зберігати його у тимчасовому значенні та називати його зв'язаним використанням call.

Для методів прототипу вам не потрібно турбуватися про вищезазначене, хоча, якщо ви хочете отримати доступ до методів прототипу суперкласу, ви можете просто зателефонувати this.constructor.super.prototype.methodName. Якщо ви хочете зробити його менш багатослівним, ви, звичайно, можете додати зручності. :)


7
Лише зауваження про cls.prototypeчастину: "Спільний доступ між примірниками" призначений лише для читання значення (виклику announce). Якщо встановлено myClassInstance.announceінше значення, воно створює нове властивість у myClassInstance, тому воно застосовується лише до цього об'єкта, а не до інших примірників класу. MyClass.prototype.announceХоча призначення , вплине на всі випадки.
Меттью Крамлі

1
Немає проблем, радий допомогти! :)
Blixt

2
Дякую! Дуже сподобався! Чи можете ви показати приклад успадкування класів у такому підході.
Дмитро Голубєв

2
@DmitrijGolubev, Brad Dwyer та Nathan C. Tresch: Я додав спадщину, але це стає досить складним, тому я б зазвичай радив вам підійти з більш простим рішенням, якщо вам не потрібна така спадкована спадщина в JavaScript (що насправді просто прототипічна мова).
Blixt

1
@guiomie Це "загальнодоступний статичний" метод, тому ви б назвали це функцією конструктора ("клас"), а не екземпляром:MyClass.get_nextId()
Blixt

166

Мені здається, більшість із вас наводить приклад getters та setters, а не конструктор, тобто http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming) .

lunched-dan був ближче, але приклад не працював у jsFiddle.

Цей приклад створює функцію приватного конструктора, яка запускається лише під час створення об'єкта.

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

Якщо ви хочете призначити загальнодоступні властивості, конструктор може бути визначений як такий:

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

45
Як це не відповідь №1? Тільки Джон створив конструктор з параметрами.
Реп

1
Чи можна отримати приклад успадкування, використовуючи цю парадигму для конструкторів?
Натан К. Треш

1
Приклад конструктора @Rap Jon не має жодних параметрів, оскільки це Box()функція :). Але цей приклад, а також приклади в інших відповідях можна легко розширити, щоб прийняти параметри.
Олександр Степанюк

2
@AndersonGreen можна додати параметр до Box і потім передати його приватному конструктору як функціональний параметр.
Gautham C.

1
Не потрібно «приватних конструкторів». Просто зробіть свою конструкцію у Boxфункції, і ви готові йти (вона все ще "приватна"). "Приватне" в JavaScript просто означає доступний через лексичну область; не потрібно призначати членів. Додатково: цей код неправильний. Це створює глобальну __constructзмінну, що досить погано. varслід використовувати для обмеження сфери застосування __construct.
mattbasta

23

Тож який сенс властивості "конструктор"? Не можете зрозуміти, де це може бути корисно, будь-які ідеї?

Суть властивості конструктора полягає в тому, щоб надати певний спосіб робити вигляд, що JavaScript має класи. Одне з речей, які ви не можете корисно зробити, - це змінити конструктор об'єкта після його створення. Це складно.

Я написав досить вичерпний твір кілька років тому: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html


Сенс полягає у використанні «нового» ключового слова. "d = new Drofto ()" створює порожній об'єкт і запускає функцію Drofto із зазначеним новим об'єктом, обмеженим як "це". Функція Drofto вільна повернути що завгодно, але прийнято повертати щось, що вважається членом класу Drofto.
Хуан Ланус

16

Приклад тут: http://jsfiddle.net/FZ5nC/

Спробуйте цей шаблон:

<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>

Ви повинні налаштувати простір імен, якщо ви визначаєте статичний клас:

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

Приклад класу:

<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>

Приклад інстанції:

<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>

Функції сповіщення визначаються як AB = функція A_B (). Це полегшує налагодження вашого сценарію. Відкрийте панель обстеження елементів Chrome, запустіть цей сценарій та розгорніть відстань відстеження:

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

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

Fail.Test();
</script>

Приклад додано. Також додана інформація про поліпшення виводу налагодження.
бітлатер

1
Можливо, тому, що це додає непотрібного рівня складності проблеми. Важко знайти відповідь у своєму дописі через педантичний інтервал імен та статичне оголошення класу. Не зрозумійте мене неправильно, це гарна інформація, але це, звичайно, більш заплутано, ніж корисно, якщо ви намагаєтесь зрозуміти ногу у двері. Я на півдорозі компетентний в JS і ледве розумію, що ти тут робиш, або чому це стосується "Як я конструктор?"
Bmo

1
Дякую за розуміння, Bmo. Це була тривала публікація, але це тому, що я не розумію використання конструктора, якщо він не прив'язаний до чітко визначеного об'єкта та реалізації статичного класу. Вивчаючи C ++ або Java, ви повинні навчитися реалізовувати класи поряд із тим, як реалізувати конструктори. Веб-розробник став набагато приємнішим з тих пір, як я натрапив на цей метод написання JavaScript, і я просто хотів поділитися. Я перемістив скрипку вгору, щоб її було легше знайти. Я сподіваюся, що це прояснить будь-яку плутанину.
бітлатер

1
@Bmo Ви серйозно ставитеся до того, що два рядки про простір імен важко знайти конструктор саме нижче, особливо з огляду на коментар Конструктор - ОБОВ'ЯЗКОВО БУТИ В ТОПУ ФАЙЛУ? Надання прикладу з простором імен дуже вітається, спільнота jav-розробників сліпо ігнорує простори імен, що спричиняє важкість пошуку помилок при зіткненні імен. Сумно бачити, що js devs думає, якщо вони копіюють фрагмент тексту з допису в Інтернеті і роблять щось подібне до того, що їм потрібно, щоб їх робота була повною.
користувач3285954

1
Основна проблема з js та веб-розробкою в цілому полягає в тому, що більшість розробників ігнорують усі практики, які створила індустрія за 50+ років, і думають, чи зможуть вони зробити аякс-дзвінок, що вони є королем. Настільки сумно бачити, що знадобилося стільки років, щоб почати використовувати відомі зразки та практики в JavaScript.
користувач3285954

10

Це конструктор:

function MyClass() {}

Коли ви робите

var myObj = new MyClass();

MyClass виконується, і новий об’єкт повертається цього класу.


1
Щоб уточнити, що це означає, що знаходиться у верхній частині вашого класу, ви можете сказати, alert(valuePassedInAsArgument);і це буде працювати один раз для кожної інстанції, тому весь клас є самим конструктором.
Мартін Лін

new object is returned of that class- хіба це не більше, як новий об’єкт повертається з цієї функції?
Дон Чідлл

у функціях javascript є об’єкти
Лев

8

Я вважав цей підручник дуже корисним. Цей підхід використовується більшістю плагінів 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;    
};

Тепер,

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]"

10
Я плачу, коли я бачу людей, які використовуютьklass
Madbreaks

8

Ця картина мені добре послужила. За допомогою цього шаблону ви створюєте класи в окремих файлах, завантажуєте їх у загальний додаток "за потребою".

// 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");

Це змінні екземпляри, але вони мають "публічну" доступність, а не "приватну", як у C ++ або Java.
Potatoswatter

Як би ви вирішили створити приватну змінну (у класичному розумінні), яка відносно екземпляра, але не спільна для всіх примірників?
боб

Дивіться на сайті Дугласа Крокфорда , він є одним з мовних дизайнерів і головним авторитетом. Я не завжди дотримуюся його шаблонів, але загалом приватна змінна є локальною varв конструкторі (або аргументі функції, або в функції, подібній конструктору).
Potatoswatter

Дякую за пораду ... на наступній сторінці пояснюється, що я шукав: javascript.crockford.com/private.html
bob

О, вибачте, що не тестували посилання: P
Potatoswatter


6

Я думаю, я опублікую те, що роблю із закриттям JavaScript, оскільки ніхто ще не використовує закриття.

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);
    }
  };
};

Зауваження та пропозиції до цього рішення вітаються. :)


1
Пара коментарів: 1) твердження, якщо (! Id) не є безпечним, значення, такі як 0 або false, змусять його оцінити істинне та повернути нулеве значення. Я здогадуюсь, що ви хочете перевірити, чи не визначено чи null, у цьому випадку === null та === undefined було б краще. 2) Це більше нагадує модель модуля ( adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth ) проти конструктора, різниця в тому, що модуль повертає об'єкт з функції, тоді як конструктор створює об'єкт, коли в парі з новим ключовим словом, і в такому випадку ви б встановили значення "це" замість об'єкта.
Багатий

4

Використовуючи приклад Ніка вище, ви можете створити конструктор для об'єктів без параметрів, використовуючи оператор return як останній вислів у вашому визначенні об'єкта. Поверніть свою конструкторську функцію, як показано нижче, і вона запустить код у __construct щоразу, коли ви створюєте об'єкт:

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

  this.color = '';

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

   __construct();
}

var b = new Box();

1
Ви не повертаєте функцію конструктора, ви просто викликаєте її.
Девід Конрад

Якщо ви спробуєте скористатися this.getColor();на лінії вище, alert("Object Created.");нічого не буде оповіщено. Буде помилка типу "getColor не визначено". Якщо ви хочете, щоб конструкція могла викликати інші методи в об'єкті, це потрібно визначити після всіх інших методів. Тож замість виклику __construct();на останньому рядку просто визначте конструкцію там і поставте ()після неї, щоб змусити її автоматично виконувати.
thinsoldier

Корекція. Додавання ()до кінця визначення __construct все ж призвело до помилки. Мені довелося зателефонувати __construct();по його власній лінії, як у вихідному коді, щоб уникнути помилки.
thinsoldier

4

Можливо, це стало трохи простіше, але нижче - що я придумав зараз у 2017 році:

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

Використовуючи клас вище, я маю наступне:

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());

Як бачите, конструктор бере два параметри, і ми встановлюємо властивості об'єкта. Ми також змінюємо колір та форму об'єкта за допомогою setterфункцій та доводимо, що його зміна залишилася після викликуgetInfo() після цих змін.

Трохи пізно, але сподіваюся, це допомагає. Я перевірив це за допомогою mochaмодульного тестування, і воно працює добре.


3

Вони роблять, якщо ви використовуєте Typescript - відкритий код від MicroSoft :-)

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

Typescript дозволяє "підробляти" OO-конструкції, які компілюються в javascript-конструкти. Якщо ви починаєте великий проект, це може заощадити вам багато часу, і він лише досягнув версії 1.0 версії.

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

Вищевказаний код 'компілюється' для:

var BankAccount = (function () {
    function BankAccount(initially) {
        this.balance = initially;
    }
    BankAccount.prototype.deposit = function (credit) {
        this.balance += credit;
        return this.balance;
    };
    return BankAccount;
})();

Я працюю над великим проектом і намагаюся переконати людей у ​​тому, що TypeScript дасть нам пробіг. Ми побачимо, як це йде.
wootscootinboogie

@wootscootinboogie За один день (закінчуючи о 5:30 ранку зараз) у мене досить далеко і досить комфортно з ним. Я настійно рекомендую прочитати специфікацію, і, хоча ви можете пропустити половину справжнього азотного зернистого матеріалу, ви робите собі послугу, прочитавши її хоча б раз. відео цього хлопця - чудові youtube.com/user/basaratali/videos . удачі)
Simon_Weaver

1

У JavaScript тип виклику визначає поведінку функції:

  • Пряме виклик func()
  • Викликання методу на об'єкт obj.func()
  • КонструкторВикликnew func()
  • Непряме виклик func.call()абоfunc.apply()

Функція викликається конструктором при виклику за допомогою newоператора:

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

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

Будь-який екземпляр або об'єкт-прототип у JavaScript мають властивість constructor, яка посилається на функцію конструктора.

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

Перевірте цю публікацію про властивість конструктора.


0

Користуючись чудовим шаблоном Blixt зверху, я виявив, що він не працює добре при багаторівневому успадкуванні (MyGrandChildClass розширює MyChildClass, що розширює MyClass) - він циклично викликає конструктор першого батька знову і знову. Отже, ось просте вирішення - якщо вам потрібне багаторівневе успадкування, замість того, щоб this.constructor.super.call(this, surName);використовувати chainSuper(this).call(this, surName);з функцією ланцюга, визначеною так:

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

0

http://www.jsoops.net/ дуже добре підходить для oop в Js. Якщо надається приватна, захищена, публічна змінна та функція, а також функція спадкування. Приклад коду:

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

0

просто запропонувати якусь різноманітність. ds.oop - хороший спосіб оголосити класи з конструкторами в JavaScript. Він підтримує всі можливі типи успадкування (включаючи 1 тип, який навіть c # не підтримує), а також інтерфейси, що приємно.

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

0

Тут нам потрібно помітити один момент у Java-скрипті, це мова без класу, проте ми можемо досягти цього, використовуючи функції в сценарії java. Найпоширеніший спосіб досягти цього нам потрібно створити функцію в сценарії java та використовувати нове ключове слово для створення об’єкта та використовувати це ключове слово для визначення властивостей та методів. Нижче наведено приклад.

// 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

-2

У більшості випадків вам потрібно якось задекларувати потрібне вам властивість, перш ніж ви зможете викликати метод, який передається в цій інформації. Якщо вам не потрібно спочатку встановлювати властивість, ви можете просто викликати такий метод у межах об'єкта. Напевно, це не самий гарний спосіб зробити це, але це все ще працює.

var objectA = {
    color: ''; 
    callColor : function(){
        console.log(this.color);
    }
    this.callColor(); 
}
var newObject = new objectA(); 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.