Конструкторы в объектах JavaScript


Ответы:


408

Использование прототипов:

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

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

Сокрытие «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
@ Джич, да, это так. Я предоставил альтернативный фрагмент, который скрывается color. Я бы предположил, что вы используете в значительной степени зависит от личных предпочтений (защита против простоты)
Ник

6
@CamiloMartin Хотя это не всегда необходимо, создание переменной «private» (или, в данном случае, безымянной) может быть полезным способом предотвращения зависимости внешнего кода от деталей реализации вашего класса. Даже просто указание того, какие элементы класса являются публичными / приватными, может быть полезным для внешних пользователей.
Ник

49
varделает приватную переменную. thisделает публичную переменную
EhevuTov

3
@AlanKis (по крайней мере, в некоторых движках Javascript) трассировка стека в случае анонимной функции даже не упоминается Foo, тогда как в последнем случае она будет знать, что она Fooвызывается. Очень полезно для отладки.
Иоахим Исакссон

248

Вот шаблон, который я иногда использую для ООП-подобного поведения в 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, Брэд Дуайер и Натан С. Треш: Я добавил наследование, но оно становится довольно сложным, поэтому я обычно советую вам перейти к более простому решению, если вам не нужно такое жесткое наследование в JavaScript (которое на самом деле просто прототип языка).
Blixt

1
@guiomie Это «публичный статический» метод, поэтому вы должны вызывать его для функции конструктора («класс»), а не для экземпляра:MyClass.get_nextId()
Blixt

166

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

Ланч-дан был ближе, но пример не работал в 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 Пример конструктора Джона не имеет параметров, так как это Box()функция :). Но этот пример, а также примеры в других ответах могут быть легко расширены для принятия параметров.
Александр Степанюк

2
@AndersonGreen, вы можете добавить параметр в Box, а затем передать его частному конструктору в качестве параметра функции.
Gautham C.

1
Там нет необходимости для "частных конструкторов". Просто сделайте свою конструкцию в Boxфункции, и вы готовы (это все еще "личное"). «Приватный» в Javascript означает просто доступ через лексическую область; нет необходимости назначать членам. Дополнительно: этот код неверен. Это создает глобальную __constructпеременную, что довольно плохо. varследует использовать для ограничения сферы действия __construct.
Маттбаста

23

Так в чем же смысл свойства "конструктор"? Не можете понять, где это может быть полезно, какие-либо идеи?

Смысл свойства конструктора состоит в том, чтобы обеспечить некоторый способ притворяться, что JavaScript имеет классы. Одна из вещей, которую вы не можете использовать , это изменить конструктор объекта после его создания. Это сложно.

Я написал довольно обширную статью об этом несколько лет назад: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html


Дело в том, чтобы использовать ключевое слово «новый». «d = new Drofto ()» создает пустой объект и запускает функцию Drofto с указанным новым объектом, ограниченным как «this». Функция 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 = function 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
Спасибо за понимание, БМО. Это был длинный пост, но это потому, что я не понимаю, как использовать конструктор, если он не привязан к четко определенному объекту и реализации статического класса. При изучении C ++ или Java вы должны научиться реализовывать классы вместе с конструкторами. С тех пор, как я наткнулся на этот метод написания javascript, веб-разработчик стал намного приятнее, и я просто хотел поделиться им. Я переместил скрипку наверх, чтобы ее было легче найти. Я надеюсь, что это прояснит любую путаницу.
Битлзер

1
@Bmo Вы серьезно относитесь к тому, что две строки о пространстве имен затрудняют поиск конструктора точно ниже, особенно с учетом комментария «Конструктор» - ДОЛЖЕН БЫТЬ НА ТОП ФАЙЛА? Предоставление примера с пространством имен очень приветствуется, сообщество разработчиков javascript слепо игнорирует пространства имен, вызывая трудности при обнаружении ошибок при столкновении имен. Грустно видеть, что js devs думают, копируют ли они текст из поста в Интернете и делают что-то похожее на то, что им нужно, их работа завершена.
user3285954

1
Основная проблема с js и веб-разработкой в ​​целом заключается в том, что большинство разработчиков игнорируют все практики, которые создавала индустрия за 50 с лишним лет, и думают, что если они смогут сделать вызов ajax, то они - король. Так печально видеть, что потребовалось столько лет, чтобы начать использовать хорошо известные шаблоны и практики в javascript.
user3285954

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

Ой, извините за то, что не протестировал ссылку: P
Potatoswatter

8

Да, вы можете определить конструктор внутри объявления класса следующим образом:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

для версии IE> 12
zloctb


1
Это единственный фактический ответ на вопрос. : /
MarcD

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, приведут к тому, что он оценит true и вернет null. Я предполагаю, что вы хотите проверить наличие неопределенного или нулевого значения, в этом случае === пустое значение и === неопределенное будет лучше. 2) Это больше напоминает шаблон модуля ( адекватно good.com/2010/3/JavaScript-Module-Pattern-In-Depth ) в сравнении с конструктором, отличие состоит в том, что модуль возвращает объект из функции, тогда как конструктор создает объект, когда в паре с новым ключевым словом, и в этом случае вы будете устанавливать значения «this» вместо объекта.
Богатый

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-конструкции. Если вы начинаете большой проект, он может сэкономить вам много времени, и он только что достиг версии milestone 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);use chainSuper(this).call(this, surName);с функцией chain, определенной следующим образом:

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/ достаточно хорош для упс в 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.