Как избавиться от зацикливания кода при использовании вложенных функций
Друзья, и снова нужна помощь знающих людей. Есть у меня простенькая функция для построения таблиц и функция для заполнения этой самой таблицы:
function createTableEmpty(id, colRows, colColums) {
let table = document.getElementById(id);
let caption = document.createElement('caption')
caption.id = "caption"
caption.className = "text2"
for (let i = 0; i < colRows; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < colColums; j++) {
let td = document.createElement('td');
td.id = `tc${i}${j}`
if (i == 0) {
td.className = "cell4 cell"
} else {
td.className = "cell4"
}
tr.appendChild(td);
}
table.appendChild(caption);
table.appendChild(tr);
}
}
function printDataResTest(data) {
let j = 0;
let property = Object.getOwnPropertyNames(data)
for (var i = 0; i < property.length; i++) {
if (Array.isArray(data[property[i]])) {
for (var k = 0; k < data.rows.length; k++) {
document.getElementById(`tc${k}${j}`).innerHTML = data[property[i]][k]
}
j++
}
}
};
функция построения таблицы принимает в себя "место построения" в хтмл, а так же количество столбцов и строк будущей таблицы, которые вычисляются на основе количества массивов в базовой переменной resName, которая является обьектом, (количество столбцов) и длины этих массивов (количество строк).
После того, как таблица построена, она начинает заполняться содержимым массивов из переменной resName.
Сама переменная выглядит следующим образом:
const HSS = HERO.sexStats;
let resName = {
name: ['Act', 'Virginity', 'Pregnant', 'Birth', 'Fertilization', 'Vaginal sex', 'Anal sex', 'Oral sex', 'Piss drinking', 'Rimjob', 'Footjob', 'Breastjob'],
get data1() {
let a = [];
a[0] = 'Data'
if (HSS.virginity == 0) {
a[1] = 'Yes'
} else {
a[1] = 'No'
}
if (HERO.genderStats.pregnancy == 1) {
a[2] = 'Yes'
} else {
a[2] = 'No'
}
if (HERO.genderStats.birth != 0) {
a[3] = HERO.genderStats.birth
} else {
a[3] = 'No'
}
if (HERO.genderStats.inseminate == 'Yes') {
a[4] = 'Yes'
} else {
a[4] = 'No'
}
for (var i = 0; i < this.support.dom.length; i++) {
a[i+5] = this.support.dom[i] + this.support.sub[i];
}
return a;
},
get data2() {
let j = 0
let a = []
let b = ['Virginity', 'Pregnant', 'Birth', 'Fertilization']
for (var i = 0; i < this.name.length; i++) {
if (this.name[i] == 'Act') {
a[i] = 'Details'
} else {
if (b.includes(this.name[i])) {
a[i] = '';
} else {
a[i] = `Dom: ${this.support.dom[j]} </br> Sub: ${this.support.sub[j]}`
j++
}
}
}
if (this.data1[4] == 'Yes') {
a[4] = HSS.sexFertilization
} else {
a[4] = '';
}
return a;
},
get rows() {
let a = this.name.length;
return a;
},
get colums() {
let a = 0
let property = Object.getOwnPropertyNames(this)
console.log('property: ', property)
for (var i = 0; i < property.length; i++) {
if (Array.isArray(this[property[i]])) {
a++
}
}
return a;
},
get keys() {
return objectKey(this)
},
support: {
dom: [HSS.sexVaginalDom, HSS.sexAnalDom, HSS.sexOralDom, HSS.pissDrinkingDom, HSS.sexRimjobDom, HSS.sexFootjobDom, HSS.sexBreastjobDom,],
sub: [HSS.sexVaginalSub, HSS.sexAnalSub, HSS.sexOralSub, HSS.pissDrinkingSub, HSS.sexRimjobSub, HSS.sexFootjobSub, HSS.sexBreastjobSub,],
id: [
['tc00', 'tc01', 'tc02'],
['tc10', 'tc11', 'tc12'],
['tc20', 'tc21', 'tc22'],
['tc30', 'tc31', 'tc32'],
['tc40', 'tc41', 'tc42'],
['tc50', 'tc51', 'tc52'],
['tc60', 'tc61', 'tc62'],
['tc70', 'tc71', 'tc72'],
['tc80', 'tc81', 'tc82'],
['tc90', 'tc91', 'tc92'],
['tc100', 'tc101', 'tc102'],
['tc110', 'tc111', 'tc112'],
],
},
};
function objectKey(obj) {
let keys = Object.keys(obj)
return keys;
}
createTableEmpty('tableHeroStats', resName.rows, resName.colums);
printDataResTest(resName);
Как можно увидеть из кода, внутри нее много геттеров, которые производят вычисления сразу по ходу выполнения кода. Но вот тут-то и возникла проблема: каждый раз, когда функция построения таблицы и/или функция ее заполнения выполняет цикл, все геттеры начинают производить перерасчёты заново.
В результате, код зависает (или скорее выполняется крайне долго. Настолько долго, что компилятор просто прерывает данную процедуру, решив, что процесс бесконечен).
Итак, мой вопрос: можно ли как-то преобразовать геттеры, чтобы они не выполняли перерасчет при каждом новом шаге цикла функции построения таблицы и/или ее заполнения, а выполнялись лишь раз, при первом запуске, а после просто хранили полученное значение?
============================================================================
let resName = {
name: ['Act', 'Virginity', 'Pregnant', 'Birth', 'Fertilization', 'Vaginal sex', 'Anal sex', 'Oral sex', 'Piss drinking', 'Rimjob', 'Footjob', 'Breastjob'],
data1: [],
data2: [],
get creatData1() {
let a = [];
if (this.data1.length != 0) {
return this.data1
} else {
a[0] = 'Data'
if (HSS.virginity == 0) {
a[1] = 'Yes'
} else {
a[1] = 'No'
}
if (HERO.genderStats.pregnancy == 1) {
a[2] = 'Yes'
} else {
a[2] = 'No'
}
if (HERO.genderStats.birth != 0) {
a[3] = HERO.genderStats.birth
} else {
a[3] = 'No'
}
if (HERO.genderStats.inseminate == 'Yes') {
a[4] = 'Yes'
} else {
a[4] = 'No'
}
for (var i = 0; i < this.support.dom.length; i++) {
a[i+5] = this.support.dom[i] + this.support.sub[i];
}
//return a;
this.data1 = a
}
},
get creatData2() {
let j = 0
let a = [];
let b = ['Virginity', 'Pregnant', 'Birth', 'Fertilization']
if (this.data2.length != 0) {
return this.data2
} else {
for (var i = 0; i < this.name.length; i++) {
if (this.name[i] == 'Act') {
a[i] = 'Details'
} else {
if (b.includes(this.name[i])) {
a[i] = '';
} else {
a[i] = `Dom: ${this.support.dom[j]} </br> Sub: ${this.support.sub[j]}`
j++
}
}
}
if (this.data1[4] == 'Yes') {
a[4] = HSS.sexFertilization
} else {
a[4] = '';
}
//return a;
this.data2 = a
}
},
get rows() {
let a = this.name.length;
return a;
},
colums: 0,
get sumColums() {
let a = 0
if (this.colums != 0) {
return this.colums
} else {
let property = Object.keys(this)
console.log('property: ', property)
for (var i = 0; i < property.length; i++) {
if (Array.isArray(this[property[i]])) {
a++
}
}
this.colums = a;
}
},
support: {
dom: [HSS.sexVaginalDom, HSS.sexAnalDom, HSS.sexOralDom, HSS.pissDrinkingDom, HSS.sexRimjobDom, HSS.sexFootjobDom, HSS.sexBreastjobDom,],
sub: [HSS.sexVaginalSub, HSS.sexAnalSub, HSS.sexOralSub, HSS.pissDrinkingSub, HSS.sexRimjobSub, HSS.sexFootjobSub, HSS.sexBreastjobSub,],
id: [
['tc00', 'tc01', 'tc02'],
['tc10', 'tc11', 'tc12'],
['tc20', 'tc21', 'tc22'],
['tc30', 'tc31', 'tc32'],
['tc40', 'tc41', 'tc42'],
['tc50', 'tc51', 'tc52'],
['tc60', 'tc61', 'tc62'],
['tc70', 'tc71', 'tc72'],
['tc80', 'tc81', 'tc82'],
['tc90', 'tc91', 'tc92'],
['tc100', 'tc101', 'tc102'],
['tc110', 'tc111', 'tc112'],
],
},
};
Ответы (2 шт):
можно ли как-то преобразовать геттеры, чтобы они не выполняли перерасчет при каждом новом шаге цикла функции построения таблицы и/или ее заполнения, а выполнялись лишь раз, при первом запуске, а после просто хранили полученное значение?
Конечно можно. По-сути вы сами ответили на свой же вопрос.
Задайте в объекте переменные с типом массив, которые изначально пустые. В геттерах вначале нужно сделать проверку, если эта внутренняя переменная не пуста - возврать данные оттуда, если пустые - то делать все манипуляции и заносить эти данные в переменные.
Вообще, если планируется только единожды заполнить данные и потом их использовать в геттерах, то, в таком случае, нужно сделать отдельные методы с логикой просчёта, которые вызовуться в конструкторе объекта. Там данные заскладировать во внутренние переменные объекта (как я написал выше), а геттер будет потом просто брать из них данные
Данный код, имеет 2 проблемы:
- не правильное использование
геттераrows - рекусия.
Помимо этого присутсвует избыточность и плохое форматирование кода (рекомендуется прочесть "Чистый Код")
Первая проблема выражена в том что:
get rows() {
let a = this.name.length;
return a;
},
по сути возвращает this.name.length что является однозначно числом поэтому использование в таком контексте:
for (var k = 0; k < data.rows.length; k++) {
document.getElementById(`tc${k}${j}`).innerHTML = data[property[i]][k]
}
просто является неприемлимым (брать length у числа, не имеет ни какого смысла) вероятно это произошло из-за невнимательности к собственному коду.
Первая часть решения:
get rows() {
return this.name;
},
Заводить переменную a в данном случае лишено смысла ибо мы возвращаем объект по ссылке в любом случае один и тот же (это один из примеров борьбы с избыточностью).
Вторая проблема выражена в том что:
get sumColums() {
let a = 0
if (this.colums != 0) {
return this.colums
} else {
let property = Object.keys(this)
console.log('property: ', property)
for (var i = 0; i < property.length; i++) {
if (Array.isArray(this[property[i]])) {
a++
}
}
this.colums = a;
}
},
Данная функция в конкретно этом коде вызывает сама себя при попытке обращения к this[property[i]] где property[i] в какой-то момент цикла эквивалентно 'sumColums' таким образом исключив этот ключ геттера можно решить проблему с рекурсией:
Вторая часть решения:
get sumColums() {
let a = 0
if (this.colums != 0) {
return this.colums
} else {
let property = Object.keys(this)
console.log('property: ', property)
for (var i = 0; i < property.length; i++) {
if (property[i] === 'sumColums') continue // добавлено для пропуска
if (Array.isArray(this[property[i]])) {
a++
}
}
this.colums = a;
}
},