提问人:tekkyprograms 提问时间:8/20/2023 最后编辑:tekkyprograms 更新时间:8/21/2023 访问量:37
为什么这个“解密”函数在这个 JavaScript 文件中不起作用?
why is this "decryption" function not working in this javascript file?
问:
我正在使用 HTML、CSS 和 Javascript 创建一个网站。我的主页由一个标题和 4 个指向其他页面(主页、关于、投资组合、联系人)的导航链接组成。我想达到这样的效果:当用户加载主页时,所有文本都在从一个密码切换到另一个密码,然后逐个字符“解密”为正确的原始文本。例如,带有原始纯文本“我的网站”的标题将显示 35 个相同长度的不同密码,然后在显示最后一个密码后逐个字符解密:bdhyfiendk -> Mhdvrufgne -> Myhdbnfehs -> My hsnrifm -> My Whsnfje -> My Wehsbeq ...你明白了。在我的 HTML 代码中,我分隔了每个文本,因此标题为 class = “.header-text”,然后 4 个导航元素遵循语法 class =“.nav-”。
到目前为止,我编写的代码正确地执行了密码位(因此它显示了所有不同的密文),但随后卡在最后一个密码上并且没有继续解密。下面是 js 文件:
// Function to generate random foreign symbols
function generateRandomSymbols(length) {
// Define a string of symbols to choose from
const symbols = "!@#$%^&*()_+-=[]{}|;':\",.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result = '';
// Generate a random string of symbols with the specified length
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * symbols.length);
result += symbols.charAt(randomIndex);
}
return result;
}
// Function to decrypt the text
function decryptHeader(textElement, originalText, decryptionSpeed) {
let currentIndex = 0;
// Function to update the text character by character
function updateText() {
if (currentIndex < originalText.length) {
const charIndex = currentIndex;
const char = originalText.charAt(charIndex);
// Create a new text string with one character replaced
const newText = textElement.textContent.substring(0, charIndex) + char + textElement.textContent.substring(charIndex + 1);
// Update the text with the new string
textElement.textContent = newText;
currentIndex++;
// Schedule the next character update with a delay
setTimeout(updateText, decryptionSpeed); // Adjust the decryption speed
}
}
// Start updating the text
updateText();
}
// Call the decryptText function for each element when the page loads
document.addEventListener('DOMContentLoaded', function () {
// Find the elements in the HTML using their classes
const headerElement = document.querySelector('.header-text');
const homeElement = document.querySelector('.nav-home');
const aboutElement = document.querySelector('.nav-about');
const portfolioElement = document.querySelector('.nav-portfolio');
const contactElement = document.querySelector('.nav-contact');
// Store the original texts
const originalHeaderText = headerElement.textContent;
const originalHomeText = homeElement.textContent;
const originalAboutText = aboutElement.textContent;
const originalPortfolioText = portfolioElement.textContent;
const originalContactText = contactElement.textContent;
// Set the decryption speed (time between character changes)
const decryptionSpeed = 100; // Adjust the decryption speed in milliseconds (e.g., 100 for 100ms)
// Generate an array of cipher texts with the same length as each original text
const cipherHeaderTexts = Array.from({ length: 35 }, () => generateRandomSymbols(originalHeaderText.length));
const cipherHomeTexts = Array.from({ length: 35 }, () => generateRandomSymbols(originalHomeText.length));
const cipherAboutTexts = Array.from({ length: 35 }, () => generateRandomSymbols(originalAboutText.length));
const cipherPortfolioTexts = Array.from({ length: 35 }, () => generateRandomSymbols(originalPortfolioText.length));
const cipherContactTexts = Array.from({ length: 35 }, () => generateRandomSymbols(originalContactText.length));
// Function to update cipher text and start decryption for each element
function updateCipherText(element, cipherTexts) {
let currentIndex = 0;
function updateCipher(index) {
if (index < cipherTexts.length) {
element.textContent = cipherTexts[index];
setTimeout(() => {
updateCipher(index + 1);
}, 50); // Adjust the cipher text change speed
} else {
// After displaying all cipher texts, start decrypting
decryptText(element, originalText, decryptionSpeed);
}
}
updateCipher(currentIndex);
}
// Start updating cipher text and decryption for each element
updateCipherText(headerElement, cipherHeaderTexts);
updateCipherText(homeElement, cipherHomeTexts);
updateCipherText(aboutElement, cipherAboutTexts);
updateCipherText(portfolioElement, cipherPortfolioTexts);
updateCipherText(contactElement, cipherContactTexts);
});
答:
如果您打开浏览器的 JavaScript 控制台(通常例如 F12 或 cmd+shift+j),您可以在控制台中看到错误:
未捕获的 ReferenceError:未定义 decryptText
如果你查看你的代码,你会看到在你的块中,你调用了这个函数,但再往上,你尝试调用的函数实际上是被命名为 。else
decryptText
decryptHeader
我们可以重命名它,但如果我们这样做,我们就会遇到另一个问题:
未捕获的 ReferenceError:未定义 originalText
再一次,如果你看一下你调用的位置,你可以看到我们试图传入,但那个变量不再存在:相反,我们有 5 个不同的变量。decryptText
originalText
在这一点上,我们可以通过将原始文本作为 的参数之一来修复它。updateCipherText
这是可行的,但是在达到这一点时,我注意到基本上你所有的代码现在都是结构化的,能够动态地接受任何元素并将效果应用于它(这很好!),除了设置它的部分:我们有五行来查找初始元素,五行来获取它们的文本, 五行通话等。这是大量的代码,如果你想在将来添加另一个密码元素,需要大量的重复。updateCipherText
因此,与其按类查找每个元素,不如反转该模式,以便所有要应用此效果的元素都只在 HTML 中获取一个类,然后在 JS 中,您只需找到该类的所有内容并将效果应用于所有这些元素。cypher
cypher
下面是应用了上述所有更改的代码的工作版本:
// Function to generate random foreign symbols
function generateRandomSymbols(length) {
// Define a string of symbols to choose from
const symbols =
"!@#$%^&*()_+-=[]{}|;':\",.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result = "";
// Generate a random string of symbols with the specified length
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * symbols.length);
result += symbols.charAt(randomIndex);
}
return result;
}
// Function to decrypt the text
function decryptText(textElement, originalText, decryptionSpeed) {
let currentIndex = 0;
// Function to update the text character by character
function updateText() {
if (currentIndex < originalText.length) {
const charIndex = currentIndex;
const char = originalText.charAt(charIndex);
// Create a new text string with one character replaced
const newText =
textElement.textContent.substring(0, charIndex) +
char +
textElement.textContent.substring(charIndex + 1);
// Update the text with the new string
textElement.textContent = newText;
currentIndex++;
// Schedule the next character update with a delay
setTimeout(updateText, decryptionSpeed); // Adjust the decryption speed
}
}
// Start updating the text
updateText();
}
// Set the decryption speed (time between character changes)
const decryptionSpeed = 100;
// Call the decryptText function for each element when the page loads
document.addEventListener("DOMContentLoaded", function () {
// Find the elements in the HTML using their classes
const elementsToCypher = document.querySelectorAll(".cypher");
for (const element of elementsToCypher) {
const originalText = element.textContent;
updateCipherText(element, originalText);
}
});
function updateCipherText(element, originalText) {
const cipherTexts = Array.from({ length: 35 }, () =>
generateRandomSymbols(originalText.length)
);
let currentIndex = 0;
function updateCipher(index) {
if (index < cipherTexts.length) {
element.textContent = cipherTexts[index];
setTimeout(() => {
updateCipher(index + 1);
}, 50); // Adjust the cipher text change speed
} else {
// After displaying all cipher texts, start decrypting
decryptText(element, originalText, decryptionSpeed);
}
}
updateCipher(currentIndex);
}
<div class="cypher header-text">Header</div>
<div class="cypher nav-home">Home</div>
<div class="cypher nav-about">About</div>
<div class="cypher nav-portfolio">Portfolio</div>
<div class="cypher nav-contact">Contact</div>
为了将来改进,我建议
- 确保您知道如何使用浏览器的 JS 控制台来查找和调试错误
- 在编写代码时使用像 VSCode 这样的 IDE,并带有 JS 的语言支持插件。我强烈推荐它,因为它可以帮助您在运行代码之前发现这些类型的错误(例如,它会在编辑器中以红色突出显示,因为它不存在,等等)。
decryptText
我还认为我们构建密码的方式有点奇怪,因为我们有多个调用(例如,一个用于第一个密码,一个用于第二阶段)。我认为您可以进行的另一个改进是仅生成一个包含所有步骤(包括 35 个原始密码,然后是所有后续步骤)的单个数组,然后只有一个 setTimeout 循环来遍历并应用它们。setTimeout
其他一些代码质量的东西,你可能应该把你的 和 常量从它们的函数中移出来,放在顶部,这样它们就在一起了,将来更容易地改变它们。我还建议重命名为 例如,因为在名称中包含单位会使使用该变量的代码的其他部分更具可读性,即使您在定义变量时旁边确实有注释。symbols
decryptionSpeed
decryptionSpeed
decryptionSpeedMs
我还认为很多评论实际上是多余的/没有用的,如果没有它们,你实际上可能会过得更好---例如
// Function to decrypt the text
function decryptText
这实际上什么也没告诉我,对吧。总的来说,我实际上认为,如果你的变量和函数名称可以非常明确和“自我记录”,那么最好避免注释。
评论