#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, это хорошо, просто чтобы получить представление о том, как все это будет происходить, я протестирую реальную вещь в частном порядке. Я действительно ценю ваш вклад.