【发布时间】:2022-01-04 13:36:31
【问题描述】:
我正在创建一个类中具有多个功能的 oop 项目。我有一段代码,但是由于我使用的是 bind 它不再起作用了。
document.getElementById("finalLink").innerHTML +=
"<a id='FLink' href='https://www.voetbalshop.nl/voetbalschoenen.html#' onclick='location.href=this.href+getLink(url);return false;'>Result</a>";
class QuestionControl{
/**
* @param {QuizPart[]} quiz
*/
constructor(quiz) {
this.quiz = quiz;
this.url = [];
this.questionNumber = -1;
this.button = document.getElementById('answer');
this.questionName = document.getElementById('question');
this.nextbtn = document.getElementById('nextbtn');
this.prevbtn = document.getElementById('prevbtn')
this.resultbtn = document.getElementById('FLink');
}
Initialize(){
this.NextQuestion();
}
/**
*
* @param {int} question
* @returns {QuizPart}
*/
SetQuestion(question){
if (this.questionNumber >= 0){
let oldAnswerButton = document.querySelectorAll('.filter_anwser');
// Deletes old question when the next question is clicked
for (let answerButton of oldAnswerButton) {
answerButton.style.display = 'none';
}
}
this.questionNumber = question;
let q = this.quiz[question];
// Check if your at the last question so the next button will stop being displayed.
if (this.questionNumber === Quiz.length-1) {
this.nextbtn.style.display = 'none';
this.prevbtn.style.display = 'block';
this.resultbtn.style.display = 'grid';
} else if (this.questionNumber === 0 ) {
this.nextbtn.style.display = 'block';
this.prevbtn.style.display = 'none';
this.resultbtn.style.display = 'none';
} else{
this.nextbtn.style.display = 'block';
this.prevbtn.style.display = 'block';
this.resultbtn.style.display = 'none';
}
// Displays Question
this.questionName.textContent = q.questionDescription;
this.questionName.id = "questionID";
return q;
}
NextQuestion() {
let question = this.SetQuestion.bind(this.questionNumber + 1);
// Displays answers of the questions
for (let y = 0; y < question.chosenAnswer.length; y++) {
let item = question.chosenAnswer[y];
// Display answer buttons
let btn = document.createElement('button');
btn.value = item.id;
btn.className = "filter_anwser";
btn.textContent = item.name;
this.button.appendChild(btn);
}
}
PrevQuestion() {
let question = this.SetQuestion(this.questionNumber - 1);
// Displays answers of the questions
for (let y = 0; y < question.chosenAnswer.length; y++) {
let item = question.chosenAnswer[y];
// Display answer buttons
let btn = document.querySelector('button[value="' + item.id + '"]');
btn.style.display = 'block';
console.log(btn);
}
}
/**
* Returns the parameters for the URL.
*
* @returns {string}
*/
getLink() {
let tmp = [];
for (let i = 0; i < this.url.length; i++) {
// Check if question is from the same quiz part and adds a , between chosen answers and add the right prefix at the beginning
if (this.url[i].length > 0){
tmp.push("" + Quiz[i].prefix + this.url[i].join(","))
}
}
/// If answers are from different quiz parts add a & between answers.
console.log(this.url, this.questionNumber);
return "" + tmp.join("&");
};
}
class QuizPart{
constructor(questionDescription, chosenAnswer, prefix){
this.questionDescription = questionDescription;
this.chosenAnswer = chosenAnswer;
this.prefix = prefix;
}
}
class ChosenAnswer{
constructor(id, name){
this.id = id;
this.name = name;
}
}
let Quiz = [
new QuizPart('Whats your size?', [
new ChosenAnswer('6595', '41'),
new ChosenAnswer('6598', '42'),
new ChosenAnswer('6601', '43'),
], 'bd_shoe_size_ids='),
new QuizPart('What color would you like?', [
new ChosenAnswer('6053', 'Red'),
new ChosenAnswer('6044', 'Blue'),
new ChosenAnswer('6056', 'Yellow'),
new ChosenAnswer('6048', 'Green'),
], 'color_ids='),
new QuizPart('What brand would you like?', [
new ChosenAnswer('5805', 'Adidas'),
new ChosenAnswer('5866', 'Nike'),
new ChosenAnswer('5875', 'Puma'),
], 'manufacturer_ids='),
]
let control = new QuestionControl(Quiz);
control.Initialize();
document.getElementById('nextbtn').addEventListener("click", control.NextQuestion);
document.getElementById('prevbtn').addEventListener("click", control.PrevQuestion);
control.button.addEventListener("click", function (e) {
const tgt = e.target;
// clear the url array if there's nothing clicked
if (control.url.length === control.questionNumber) {
control.url.push([]);
}
let quizUrl = control.url[control.questionNumber];
// Check if a button is clicked. Changes color and adds value to the url array.
if (quizUrl.indexOf(tgt.value) === -1) {
quizUrl.push(tgt.value);
e.target.style.backgroundColor = "orange";
// Check if a button is clicked again. If clicked again changes color back and deletes value in the url array.
} else {
quizUrl.splice(quizUrl.indexOf(tgt.value), 1);
e.target.style.backgroundColor = "white";
}
console.log(control.getLink());
})
问题是当我开始使用 bind 将函数 SetQuestion 连接到 NextQuestion 时,它给了我以下错误:
Uncaught TypeError: Cannot read properties of undefined (reading 'length')
在 nextQuestion 的 for 循环中,但如果我停止使用 bind,它将无法识别函数 SetQuestion。有人知道为什么会这样吗?
【问题讨论】:
-
"使用bind将函数
SetQuestion连接到NextQuestion":什么意思?我在您的代码中没有看到任何bind?通常bind不用于将函数绑定到另一个函数,而是绑定到类实例对象。 -
你在哪里使用
bind?我在您的代码中的任何地方都找不到它。 -
你的代码不是客户端javascript,不是吗?
-
在使用它的地方不需要
bind。只需致电this.SetQuestion(...)。您需要bind的地方是添加事件侦听器时。 -
@trincot 我添加了绑定,我不小心添加了旧代码。我在 NextQuestion 函数的第一行中使用了 bind,但我不太了解 JavaScript 面向对象。我不知道如何正确地做到这一点。
标签: javascript loops oop