javascript 中最好的 "practice" 或代码形式是什么(示例)
What is the best "practice" or form of code in javascript (example)
我目前正在做 CS50。我对 javascript 感到有点迷茫,我不知道做事或编写“正确代码”的最佳方法。
我觉得在 C 和 Python 中,行事更清晰。 (不要重复代码,使其清晰易读等)在 javascript 中,我们可以通过多种方式做事,但我不知道哪一种是正确的。
例如,我花了几天时间来解决问题,这个问题要求我们制作按钮,如果按钮答案不正确,按钮会变成红色,如果答案正确,按钮会变成绿色,我知道离开是个好习惯一个文件中的所有 javascript 与 html 不同,首先我只在 html 中使用 onclick 来调用我在 js 文件中实现的函数然后我尝试将其更改为不html 页面中没有任何 js 代码。
所以我想删除 onclick 调用,所以,我将加载的 javascript 和 addEventListener 放在 javascript 上,并在那里执行所有功能,有了这个,我想检查按钮的 innerHtml 是否是与正确答案相同,但这段代码不起作用,我认为这段代码是正确的版本,因为它确实在检查答案是否正确
window.addEventListener("load", function () {
//Declaring first function
function checkAnswer(event) {
var buttonPressed = event.Target;
if (buttonPressed.innerHTML == 'Uruguay')
{
buttonPressed.style.background = "green";
}
else:
{
buttonPressed.style.background = "red";
}
var buttons = document.querySelectorAll('button');
buttons.forEach(b => b.addEventListener("click", checkAnswer(event)));
}
因为我在使用这个功能时遇到了问题,所以我请一位使用 javascript 的朋友来看它,他对我说有一个简单的方法,通过正确或不正确来标识所有按钮如果用户单击正确,则执行附加到该按钮的功能以将按钮着色为绿色,如果其红色则执行另一个:
const correctButton = document.getElementById("correctButton");
const Incorrectbuttons = document.querySelectorAll("#Incorrectbutton");
bcorrectButton.addEventListener("click", function(){
correctButton.style.background = "green";
});
Incorrectbuttons.forEach(btn => {
btn.addEventListener("click", function(){
btn.style.background = "red";
});
})
我觉得这段代码作弊,因为它实际上不检查按钮是否正确,如果用户在他的浏览器中更改单词的内部 html,按钮仍然变成绿色,在我的代码,我认为如果用户更改内部 html 它不会更改,因为 innerHtml 与“键”不匹配。
我不知道我是否看错了,因为我依附于使用其他语言的其他思维方式,我可以在 javascript 上没有逻辑地“直接”做事,或者我的第一个功能是完全的错误的。谢谢!
嗯,你的代码有很多错误。但是,您的方向是正确的!
注意事项:
- 您可以在页面加载事件之外声明您的函数。
- 添加事件侦听器时,您必须传递函数,不调用它。
试试这个:
//The load event is fired when the whole page has loaded
window.addEventListener("load", function() {
//Get all buttons in the page
let buttons = document.querySelectorAll('button');
//Set a click event listener for each button
//When the event occurs then it calls the checkAnswer event handler callback and passes the event to it
//Notice that the callback function is passed and not directly called with "()"!
buttons.forEach(b => b.addEventListener("click", checkAnswer));
});
//Check answer function
function checkAnswer(event) { // <- here we get the event and use it
//Get the presses button
var buttonPressed = event.target;
//Check the content of the button
if (buttonPressed.innerHTML == 'Uruguay') {
//Change background to green
buttonPressed.style.background = "green";
} else {
//Change background to red
buttonPressed.style.background = "red";
}
}
编辑:
关于安全方面。在提供的两种代码(您的和您朋友的)中,用户都可以操作 HTML 中的数据并获得正确答案。这种检查必须是服务器端的,您告诉服务器检查用户发送的值(单击按钮的值)是否正确。然后根据服务器的回答继续显示所选择的 button/answer 是否正确。
只是为了向您展示一种语言的美 JavaScript - 这里有两种可能的方法(实际上是在很多方法中),一种是 简单,另一种是更多高级动态模板生成 - 全部来自代码中预定义的一些数据模型:
1。更简单的解决方案:
在您的父元素上使用 data-*
属性来存储正确的答案字符串。
只需将您的按钮放入 HTML 并将正确的答案值分配给父元素 data-answer
属性:
const ELS_answer = document.querySelectorAll("[data-answer]");
ELS_answer.forEach(EL => {
// Assign click handler to parent element with data-answer attribute
EL.addEventListener("click", (ev) => {
// Get the data attribute of the parent element
const correct = ev.currentTarget.dataset.answer;
// Get the text of the clicked button
const answer = ev.target.closest("button").textContent;
// Check if correct
if (answer === correct) {
alert("CORRECT! (PS: make button green here!)");
} else {
alert("Not correct :(");
}
});
});
<div data-answer="Five">
<h3>What goes after "Four"?</h3>
<button type="button">One</button>
<button type="button">Five</button>
<button type="button">Nine</button>
</div>
<div data-answer="nice">
<h3>This site is pretty ____</h3>
<button type="button">nice</button>
<button type="button">boring</button>
<button type="button">sweet</button>
</div>
<div data-answer="8">
<h3>How many bits are in a single byte?</h3>
<button type="button">4</button>
<button type="button">8</button>
<button type="button">16</button>
</div>
正如您在上面看到的,您不会用字符串污染您的JavaScript代码逻辑,并且该代码可以用于无限琐事(“多项选择”)问题和按钮的数量。
2。高级解决方案
牢记——数据!
那么,您将如何为 第 1 部分(甚至 第 2 部分 “免费回复”构建数据) 的 CS50 Lab?你有 多个 按钮(因此将其视为 数组 )而你只有 一个 正确答案.
而且你还有 types(目前有两个:Multiple choices and Free Response)因此 type
, question
, answers
, correct
都可以是 properties 每个 Object item inside trivia
数组.
可以这样建模:
const trivia = [
{
// `type` will help you create specific HTML Elements markup (template)
type: "multiple",
// The question that goes into H3
question: "What is the first word of the well known typesetting text?",
// Loop this Array values to generate your buttons!
answers: ["Ipsum", "Lorem", "Amet", "Sit", "Dolor"],
// Here you can store the correct answer
correct: "Lorem",
},
{
type: "free",
question: "What is the best community driven website for developers?",
answers: [], // will be populated by user!
correct: "Stack Overflow",
},
];
根据以上内容,您可以迭代 trivia
数组并生成 HTML.
如果当前迭代的琐事项目 type
是 "multiple"
- 生成 <h3>
和您的按钮。
如果当前迭代的琐事项目 type
是 "free"
- 生成 <h3>
、一个 <input type="text">
和一个按钮。
// Trivia HTML templates functions:
const templates = {
multiple(data) { /* GENETATE THE "MULTIPLE" TEMPLATE and append to DOM */ },
free(data) { /* GENETATE THE "FREE" TEMPLATE and append to DOM */ },
// In the future you can add more template types here
};
// Iterate your trivia objects and generate HTML
trivia.forEach((data) => {
templates[data.type](data); // call a specific template generator!
});
综上所述,你可以想问多少就问多少。
将来你可以扩展上面的 data 以获得其他有趣的 type
s.
要生成按钮,您需要做的就是迭代 data.answers
,例如:
const trivia = [
{
type: "multiple",
question: "What is the first word of the well known typesetting text?",
answers: ["Ipsum", "Lorem", "Amet", "Sit", "Dolor"],
correct: "Lorem",
},
{
type: "free",
question: "What is the best community driven website for developers?",
answers: [],
correct: "Stack Overflow",
},
];
// Utility functions
// Create a new Element tag with properties:
const newEL = (tag, props) => Object.assign(document.createElement(tag), props);
// Trivia HTML templates:
const templates = {
multiple(data) {
// Create the Heading
const H3 = newEL("h3", {textContent: data.question});
// Create the Buttons
const BUTTONS = data.answers.reduce((DF, answer) => {
// Create a single button
const BUTTON = newEL("button", {
type:"button",
textContent: answer,
onclick() {
// check if answer is correct
if (data.correct === this.textContent) {
alert("CORRECT! PS: style your button green here");
} else {
alert("Not norrect");
}
}
});
DF.append(BUTTON); // Append every button to the DocumentFragment
return DF; // Return the DocumentFragment
}, new DocumentFragment());
// Finally, append everything to a specific DOM Element parent
document.querySelector("#multiple").append(H3, BUTTONS);
},
free(data) {
// TODO!
// Similar as the above one
// You can do it!!!
}
};
// Iterate your trivia objects and generate HTML templates
trivia.forEach((data) => templates[data.type](data));
<div id="multiple"></div>
关于安全/黑客攻击
您现阶段不在担心此实验任务的安全性。但很高兴您始终牢记这一点,因为它 极其重要!
由于到达浏览器的代码(HTML、JS、网络请求等)可以被欺骗或反向工程(如上面的示例 1 中的答案硬编码在 HTML; 和示例 2. 在 JS 中是正确的),为了不允许用户看到正确的答案,正确的方法是将正确的答案存储在服务器的某个地方(用户不可见)。将用户选择的答案发送到服务器并检查服务器端的正确性。比服务器应该只响应浏览器响应(即:"correct"
/ "wrong"
),以便用户界面可以前进到下一个问题或给出最终的总分。即便如此,服务器也不应该信任用户!因此,您应该使用浏览器+后端技术实现一种用户会话,例如会话cookie,并检查来自用户的数据是否与特定数据库中的状态相匹配用户(当前问题、正确问题数、时间戳等)。
不是 CS50 实验室现阶段必须解决的主题或问题。但是,如果您愿意 - 没有人会阻止您自行探索和实施更强大、更安全的解决方案!
我目前正在做 CS50。我对 javascript 感到有点迷茫,我不知道做事或编写“正确代码”的最佳方法。 我觉得在 C 和 Python 中,行事更清晰。 (不要重复代码,使其清晰易读等)在 javascript 中,我们可以通过多种方式做事,但我不知道哪一种是正确的。
例如,我花了几天时间来解决问题,这个问题要求我们制作按钮,如果按钮答案不正确,按钮会变成红色,如果答案正确,按钮会变成绿色,我知道离开是个好习惯一个文件中的所有 javascript 与 html 不同,首先我只在 html 中使用 onclick 来调用我在 js 文件中实现的函数然后我尝试将其更改为不html 页面中没有任何 js 代码。
所以我想删除 onclick 调用,所以,我将加载的 javascript 和 addEventListener 放在 javascript 上,并在那里执行所有功能,有了这个,我想检查按钮的 innerHtml 是否是与正确答案相同,但这段代码不起作用,我认为这段代码是正确的版本,因为它确实在检查答案是否正确
window.addEventListener("load", function () {
//Declaring first function
function checkAnswer(event) {
var buttonPressed = event.Target;
if (buttonPressed.innerHTML == 'Uruguay')
{
buttonPressed.style.background = "green";
}
else:
{
buttonPressed.style.background = "red";
}
var buttons = document.querySelectorAll('button');
buttons.forEach(b => b.addEventListener("click", checkAnswer(event)));
}
因为我在使用这个功能时遇到了问题,所以我请一位使用 javascript 的朋友来看它,他对我说有一个简单的方法,通过正确或不正确来标识所有按钮如果用户单击正确,则执行附加到该按钮的功能以将按钮着色为绿色,如果其红色则执行另一个:
const correctButton = document.getElementById("correctButton");
const Incorrectbuttons = document.querySelectorAll("#Incorrectbutton");
bcorrectButton.addEventListener("click", function(){
correctButton.style.background = "green";
});
Incorrectbuttons.forEach(btn => {
btn.addEventListener("click", function(){
btn.style.background = "red";
});
})
我觉得这段代码作弊,因为它实际上不检查按钮是否正确,如果用户在他的浏览器中更改单词的内部 html,按钮仍然变成绿色,在我的代码,我认为如果用户更改内部 html 它不会更改,因为 innerHtml 与“键”不匹配。
我不知道我是否看错了,因为我依附于使用其他语言的其他思维方式,我可以在 javascript 上没有逻辑地“直接”做事,或者我的第一个功能是完全的错误的。谢谢!
嗯,你的代码有很多错误。但是,您的方向是正确的!
注意事项:
- 您可以在页面加载事件之外声明您的函数。
- 添加事件侦听器时,您必须传递函数,不调用它。
试试这个:
//The load event is fired when the whole page has loaded
window.addEventListener("load", function() {
//Get all buttons in the page
let buttons = document.querySelectorAll('button');
//Set a click event listener for each button
//When the event occurs then it calls the checkAnswer event handler callback and passes the event to it
//Notice that the callback function is passed and not directly called with "()"!
buttons.forEach(b => b.addEventListener("click", checkAnswer));
});
//Check answer function
function checkAnswer(event) { // <- here we get the event and use it
//Get the presses button
var buttonPressed = event.target;
//Check the content of the button
if (buttonPressed.innerHTML == 'Uruguay') {
//Change background to green
buttonPressed.style.background = "green";
} else {
//Change background to red
buttonPressed.style.background = "red";
}
}
编辑:
关于安全方面。在提供的两种代码(您的和您朋友的)中,用户都可以操作 HTML 中的数据并获得正确答案。这种检查必须是服务器端的,您告诉服务器检查用户发送的值(单击按钮的值)是否正确。然后根据服务器的回答继续显示所选择的 button/answer 是否正确。
只是为了向您展示一种语言的美 JavaScript - 这里有两种可能的方法(实际上是在很多方法中),一种是 简单,另一种是更多高级动态模板生成 - 全部来自代码中预定义的一些数据模型:
1。更简单的解决方案:
在您的父元素上使用 data-*
属性来存储正确的答案字符串。
只需将您的按钮放入 HTML 并将正确的答案值分配给父元素 data-answer
属性:
const ELS_answer = document.querySelectorAll("[data-answer]");
ELS_answer.forEach(EL => {
// Assign click handler to parent element with data-answer attribute
EL.addEventListener("click", (ev) => {
// Get the data attribute of the parent element
const correct = ev.currentTarget.dataset.answer;
// Get the text of the clicked button
const answer = ev.target.closest("button").textContent;
// Check if correct
if (answer === correct) {
alert("CORRECT! (PS: make button green here!)");
} else {
alert("Not correct :(");
}
});
});
<div data-answer="Five">
<h3>What goes after "Four"?</h3>
<button type="button">One</button>
<button type="button">Five</button>
<button type="button">Nine</button>
</div>
<div data-answer="nice">
<h3>This site is pretty ____</h3>
<button type="button">nice</button>
<button type="button">boring</button>
<button type="button">sweet</button>
</div>
<div data-answer="8">
<h3>How many bits are in a single byte?</h3>
<button type="button">4</button>
<button type="button">8</button>
<button type="button">16</button>
</div>
正如您在上面看到的,您不会用字符串污染您的JavaScript代码逻辑,并且该代码可以用于无限琐事(“多项选择”)问题和按钮的数量。
2。高级解决方案
牢记——数据!
那么,您将如何为 第 1 部分(甚至 第 2 部分 “免费回复”构建数据) 的 CS50 Lab?你有 多个 按钮(因此将其视为 数组 )而你只有 一个 正确答案.
而且你还有 types(目前有两个:Multiple choices and Free Response)因此 type
, question
, answers
, correct
都可以是 properties 每个 Object item inside trivia
数组.
可以这样建模:
const trivia = [
{
// `type` will help you create specific HTML Elements markup (template)
type: "multiple",
// The question that goes into H3
question: "What is the first word of the well known typesetting text?",
// Loop this Array values to generate your buttons!
answers: ["Ipsum", "Lorem", "Amet", "Sit", "Dolor"],
// Here you can store the correct answer
correct: "Lorem",
},
{
type: "free",
question: "What is the best community driven website for developers?",
answers: [], // will be populated by user!
correct: "Stack Overflow",
},
];
根据以上内容,您可以迭代 trivia
数组并生成 HTML.
如果当前迭代的琐事项目 type
是 "multiple"
- 生成 <h3>
和您的按钮。
如果当前迭代的琐事项目 type
是 "free"
- 生成 <h3>
、一个 <input type="text">
和一个按钮。
// Trivia HTML templates functions:
const templates = {
multiple(data) { /* GENETATE THE "MULTIPLE" TEMPLATE and append to DOM */ },
free(data) { /* GENETATE THE "FREE" TEMPLATE and append to DOM */ },
// In the future you can add more template types here
};
// Iterate your trivia objects and generate HTML
trivia.forEach((data) => {
templates[data.type](data); // call a specific template generator!
});
综上所述,你可以想问多少就问多少。
将来你可以扩展上面的 data 以获得其他有趣的 type
s.
要生成按钮,您需要做的就是迭代 data.answers
,例如:
const trivia = [
{
type: "multiple",
question: "What is the first word of the well known typesetting text?",
answers: ["Ipsum", "Lorem", "Amet", "Sit", "Dolor"],
correct: "Lorem",
},
{
type: "free",
question: "What is the best community driven website for developers?",
answers: [],
correct: "Stack Overflow",
},
];
// Utility functions
// Create a new Element tag with properties:
const newEL = (tag, props) => Object.assign(document.createElement(tag), props);
// Trivia HTML templates:
const templates = {
multiple(data) {
// Create the Heading
const H3 = newEL("h3", {textContent: data.question});
// Create the Buttons
const BUTTONS = data.answers.reduce((DF, answer) => {
// Create a single button
const BUTTON = newEL("button", {
type:"button",
textContent: answer,
onclick() {
// check if answer is correct
if (data.correct === this.textContent) {
alert("CORRECT! PS: style your button green here");
} else {
alert("Not norrect");
}
}
});
DF.append(BUTTON); // Append every button to the DocumentFragment
return DF; // Return the DocumentFragment
}, new DocumentFragment());
// Finally, append everything to a specific DOM Element parent
document.querySelector("#multiple").append(H3, BUTTONS);
},
free(data) {
// TODO!
// Similar as the above one
// You can do it!!!
}
};
// Iterate your trivia objects and generate HTML templates
trivia.forEach((data) => templates[data.type](data));
<div id="multiple"></div>
关于安全/黑客攻击
您现阶段不在担心此实验任务的安全性。但很高兴您始终牢记这一点,因为它 极其重要!
由于到达浏览器的代码(HTML、JS、网络请求等)可以被欺骗或反向工程(如上面的示例 1 中的答案硬编码在 HTML; 和示例 2. 在 JS 中是正确的),为了不允许用户看到正确的答案,正确的方法是将正确的答案存储在服务器的某个地方(用户不可见)。将用户选择的答案发送到服务器并检查服务器端的正确性。比服务器应该只响应浏览器响应(即:"correct"
/ "wrong"
),以便用户界面可以前进到下一个问题或给出最终的总分。即便如此,服务器也不应该信任用户!因此,您应该使用浏览器+后端技术实现一种用户会话,例如会话cookie,并检查来自用户的数据是否与特定数据库中的状态相匹配用户(当前问题、正确问题数、时间戳等)。
不是 CS50 实验室现阶段必须解决的主题或问题。但是,如果您愿意 - 没有人会阻止您自行探索和实施更强大、更安全的解决方案!