Существуют ли значимые различия в производительности для объявления переменных внутри конструктора класса javascript по сравнению с методом, вызываемым внутри указанного конструктора?

#javascript #class #class-constructors

#javascript #класс #конструкторы классов

Вопрос:

Я действительно новичок в JS и stackoverflow, но не новичок в программировании, поэтому простите меня, если на этот вопрос уже где-то был дан ответ.

Причина сделать это вторым способом заключалась бы только в том, чтобы улучшить «аккуратность» класса. Мне интересно, есть ли компромиссы в производительности для удобства чтения, если делать это таким образом.

Чтобы быть более ясным:

есть ли потеря производительности от этого:

 class MyClass{
    constructor(args){
        this.UpdateClass(args);
    }
    UpdateClass(args){
        this.firstVar = this.GetFirstVar();
        this.secondVar = this.GetSecondVar(args);
    }
    GetFirstVar(){
        return 420;
    }
    GetSecondVar(args){
        return args.Cheesesteak;
    }
}
 

Вместо того, чтобы делать это:

 class MyClass{
    constructor(args){
        this.firstVar = this.GetFirstVar();
        this.secondVar = this.GetSecondVar(args);
    }
    UpdateClass(args){
        this.firstVar = this.GetFirstVar();
        this.secondVar = this.GetSecondVar(args);
    }
    GetFirstVar(){
        return 420;
    }
    GetSecondVar(args){
        return args.Cheesesteak;
    }
}
 

Моя интерпретация чтения руководства по стилю js от Google заключалась в том, что они всегда должны объявлять переменные класса внутри конструктора, потому что объявление переменных класса внутри другого метода требует больших вычислительных затрат, но так ли это, когда метод класса определяет и / или обновляет каждую переменную класса без исключения.

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

1. Не могли бы вы предоставить какой-нибудь реальный код, пожалуйста? Большинство методов в этом классе выглядят довольно бессмысленно, и сохранение одной строки на самом деле не делает класс более «аккуратным».

2. » Моя интерпретация чтения руководства по стилю js от Google заключалась в том, что они всегда должны объявлять переменные класса внутри конструктора, потому что объявление переменных класса внутри другого метода требует больших вычислительных затрат «, где это сказано? Насколько мне известно, в руководстве по стилю упоминается только о том, чтобы не добавлять поля после завершения работы конструктора. Вызов метода из конструктора все еще выполняется до его завершения.

3. @ajos2 Конструктор, который вызывает 20 методов, звучит так, как будто в вашем дизайне есть другие проблемы.

4. Реальный запах кода здесь — это методы GetFirstVar , GetSecondVar которые не используют instance ( this ), поэтому они не должны быть методами экземпляра. Либо просто встроите их, сделайте статичными, либо даже переместите эту функциональность в отдельные функции рядом с классом.

5. @ajos2 » Свойства никогда не должны добавляться или удаляться из экземпляра после завершения работы конструктора», — опять же, вызов метода из конструктора означает, что он еще не завершен. Управление вернется к нему после завершения выполнения метода.

Ответ №1:

Хорошо, так что спасибо @Bergi и @VLAZ за их помощь в этом. В итоге я протестировал этот фрагмент кода в jsfiddle:

 class MyClass {
  constructor(data) {
    this.UpdateClass(data);
  }
  UpdateClass(data) {
    this.firstVar = this.GetFirstVar(data);
    this.secondVar = this.GetSecondVar(data);
  }

  GetFirstVar(data) {
    var first = data.slice(1, 4).join();
    return first;
  }
  GetSecondVar(data) {
    var cat = data.slice(2, 5);
    return cat;
  }
}

class MyClass2 {
  constructor(data) {
    this.firstVar = this.GetFirstVar(data);
    this.secondVar = this.GetSecondVar(data);
  }
  UpdateClass(data) {
    this.firstVar = this.GetFirstVar(data);
    this.secondVar = this.GetSecondVar(data);
  }

  GetFirstVar(data) {
    var first = data.slice(1, 4).join();
    return first;
  }
  GetSecondVar(data) {
    var cat = data.slice(2, 5);
    return cat;
  }
}

var testData = ['AB', 'AB', 'AB', 'AB', 'AB', 'AB', 'AB'];
var case1= 0;
var case2= 0;
var caseup=0;

for(let y = 0; y < 10; y  ){
  var start = new Date().getTime();
  for (let i = 0; i < 300000; i  ) {
    var testClass = new MyClass(testData);
  }
  
  var stop = new Date().getTime();
  case1  = stop - start;

  start = new Date().getTime();
  for (let i = 0; i < 300000; i  ) {
    var testClass = new MyClass2(testData);
  }
  stop = new Date().getTime();
    case2  = stop - start;

  var testClass = new MyClass(testData);
  start = new Date().getTime();
  for (let i = 0; i < 300000; i  ) {
    testClass.UpdateClass(testData);
  }
  stop = new Date().getTime();
    caseup  = stop - start;
  
}
console.log(`Difference in first case is: ${case1 / 10} ms`)
console.log(`Difference in second case is: ${case2 / 10} ms`)
console.log(`Difference in update case is: ${caseup / 10} ms`)
 
 Output (3m iterations):
Difference in first case is: 493.4 ms
Difference in second case is: 500.3 ms
Difference in update case is: 469.9 ms
 

Таким образом, в этой упрощенной версии, по-видимому, существует разница в производительности при создании экземпляра класса миллионы раз, но для значений на порядки ниже разница в производительности становится менее очевидной:

 Output (300k iterations):
Difference in first case is: 49.6 ms
Difference in second case is: 49.1 ms
Difference in update case is: 47 ms
 

РЕДАКТИРОВАТЬ: я добавил простой случай обновления и переписал тест для запуска десять раз и получения среднего значения. Результаты должны быть более надежными.

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

1. Это странно, я бы ожидал, что второй будет быстрее. Но тоже не значимо 🙂 Однако для измерения производительности вы всегда должны делать это с вашим реальным кодом (который создает 20 свойств — характеристики производительности для этого могут быть совершенно разными), и, что более важно, вам также нужно вызвать .UpdateClass метод самостоятельно, это часть вашей фактической рабочей нагрузки. Доступ к классу окажет большее влияние на производительность, если коды конструктора действительно приведут к другой инициализации свойств.

2. @Bergi, это хорошо, просто чтобы получить представление о том, как все это будет происходить, я протестирую реальную вещь в частном порядке. Я действительно ценю ваш вклад.