Метод вызова конструктора класса Javascript

#javascript #class #methods #constructor

#javascript #класс #методы #конструктор

Вопрос:

В Java вы можете вызывать методы, которые помогут вам выполнить тяжелую работу в конструкторе, но javascript требует, чтобы сначала был определен метод, поэтому мне интересно, есть ли другой способ, которым я мог бы это сделать, или я вынужден вызывать метод, который выполняет тяжелую работу после того, как он был определен. Я предпочитаю сохранять функции экземпляра, содержащиеся в объекте / классе, и мне кажется странным, что мне пришлось бы иметь конструктор в самом конце объекта / класса.

 function Polynomials(polyString)
{
    // instance variables
    this.polys = [];
    this.left = undefined;
    this.right = undefined;

    // This does not work because it's not yet declared
    this.parseInit(polyString);

    // this parses out a string and initializes this.left and this.right
    this.parseInit = function(polyString)
    {
        //Lots of heavy lifting here (many lines of code)
    }

    // A lot more instance functions defined down here (even more lines of code)

    // Is my only option to call it here?
}
 

Комментарии:

1. Это связано с подъемом и объявлениями против выражений.

Ответ №1:

Вот что я бы сделал:

 var Polynomials = function() { 
   // let's use a self invoking anonymous function
   // so that we can define var / function without polluting namespace
   // idea is to build the class then return it, while taking advantage
   // of a local scope.

   // constructor definition
   function Polynomials( value1) (
      this.property1 = value1;
      instanceCount  ;
      // here you can use publicMethod1 or parseInit
   }

   // define all the public methods of your class on its prototype.
   Polynomials.prototype = {

     publicMethod1 : function() { /* parseInit()... */ },

     getInstanceCount : function() ( return instanceCount; }

   }

  // you can define functions that won't pollute namespace here
  // those are functions private to the class (that can't be accessed by inheriting classes)
  function parseInit() {
  }

  // you can define also vars private to the class
  //  most obvious example is instance count.
  var instanceCount = 0; 

   // return the class-function just bui<
   return Polynomials;

}();
 

Примечания:

Rq 1:

функции-прототипы являются общедоступными методами, доступными для каждого экземпляра класса.

 var newInstance = new MyClass();
newInstance.functionDefinedOnPrototype(sameValue);
 

Rq2:
Если вам нужна действительно «частная» переменная, вы должны получить этот путь:

 function Constructor() {
   var privateProperty=12;
   this.functionUsingPrivateProperty = function() {  
    // here you can use privateProperrty, it's in scope
   }
}

Constructor.prototype = {
    // here define public methods that uses only public properties
    publicMethod1 : function() {
        // here privateProperty cannot be reached, it is out of scope.
    }
}
 

лично я использую только свойства (не частные переменные) и использую «общее соглашение для уведомления о том, что свойство является частным. Таким образом, я могу определить каждый общедоступный метод в прототипе.
После этого любой, кто использует свойство с префиксом «
, должен взять на себя ответственность, это кажется справедливым. 🙂

Для разницы между function fn() {} и var fn= function() {} , google или S.O. для этого вопроса короткий ответ заключается в том, что function fn() {} получает определенную функцию и присваивает ее значение во всей области видимости, когда var определяется переменная, но ее значение вычисляется только тогда, когда код выполнил оценку.

Комментарии:

1. Это похоже на потерянное руководство, которое я искал, у меня все еще есть несколько дополнительных вопросов о области видимости и экземпляре по сравнению со статическими функциями — время, чтобы начать играть и находить некоторые вещи 🙂 Мне действительно нравится, как все организовано и самодостаточно.

2. Да, это очень простой способ продолжения. У меня могут быть другие замечания, если вам интересно.

3. Являются ли прототипированные функции статическими методами? На самом деле это был следующий вопрос, который я собирался задать в stackoverflow

4. Это function parseInit() то же самое, что var parseInit = function() по какой-то причине я чувствую себя более комфортно с var — как будто это модификатор области видимости, поскольку я перехожу из Java / C #, хотя я знаю, что это не так; это то, с чем мне придется смириться.

5. @CTS_AE Это почти то же самое. Объявление переменной поднимается в обоих случаях. Однако есть важное отличие: при объявлении функции также поднимается все определение, так что вы можете вызвать функцию до того, как она была определена в коде, но это не относится к выражению функции.

Ответ №2:

Ваши «переменные экземпляра» объявляются в объекте «this», что, если вы ищете эквивалент Java, немного похоже на то, чтобы сделать их общедоступными. Вы можете объявлять переменные с var ключевым словом, что делает их более похожими на частные переменные в вашей функции конструктора. Затем они подвергаются «подъему», что в основном означает, что они считаются объявленными в верхней части вашей функции (или в любой другой области, в которой они объявлены), даже если вы пишете их после вызывающего кода.

Комментарии:

1. Никогда не знал о подъеме, спасибо за четкое и понятное объяснение.

2. Я не уверен, что это может сработать, потому что я пытаюсь ссылаться на переменные экземпляра в функции parseInit . Я предполагаю, что мне также нужно изменить их на private / var.

3. Ах, тогда вам, возможно, придется выполнить немного странно выглядящее присвоение этого переменной a la var that = this; . Затем, когда вы хотите обновить this.foo свою внутреннюю функцию, вы that.foo вместо этого ссылаетесь на . Это связано с тем, что this ключевое слово в Java немного странное, поскольку оно будет применяться к области действия внутренней функции, а не к области действия вашей функции конструктора.

4. Я помню, что мне пришлось проделать этот небольшой хакерский обходной путь в проекте около 2 лет назад; Я полностью забыл об этом до сих пор, спасибо.

Ответ №3:

Я бы создал объявление функции, а затем присвоил переменную объявлению функции. Причина в том, что JavaScript поднимет ваши объявления функций.

Итак, вы могли бы сделать это:

 function Polynomials(polyString) {
    // instance variables
    this.polys = [];
    this.left = undefined;
    this.right = undefined;

    // this parses out a string and initializes this.left and this.right
    this.parseInit = parseInitFunc;

    // This does not work because it's not yet declared
    this.parseInit(polyString);

    // A lot more instance functions defined down here (even more lines of code)

    function parseInitFunc(polyString) {
        console.log('executed');
    }

    // Is my only option to call it here?
}
 

Таким образом, ваш код остается чистым.

jsFiddle

Комментарии:

1. Но это все равно не поднимет выражение, поэтому this.parseInit = fn; оно все равно не будет определено, и вы не сможете этого сделать function this.parseInit() {...

2. Теперь вы добавили некоторый код, но он точно такой же, как у OP, разницы нет?

3. @adeneo, это требует дополнительной очистки (например, изменения моих комментариев), но он поднимает «функцию parseInitFunc», а затем присваивает this.parseInit, а затем вызывает это, по крайней мере, я считаю, что это должно произойти, я еще не пробовал это, но я никогда не знало «подъеме» до сих пор. Объяснение Rom99 сработало для меня лучше и быстрее, но эта ссылка определенно содержит некоторые глубокие детали 🙂

4. @CTS_AE — Хм, нет! Функция вызывается перед выражением, так что это точно то же самое, это ничего не меняет.

5. Теперь он будет работать с измененным порядком, но он все тот же, что и CTS_AE, упомянутый в вопросе, просто вызов функции после ее определения, конечно, будет работать.