Good day, friends!
I bring to your attention a small interactive JavaScript quiz, currently consisting of 50 questions.
In my opinion, solving such problems is the best way to determine your skill level.
Continued here .
Foreword
This part is based on this repository . Its author, Lydia Hallie, positions his project as a list of advanced questions and, indeed, among them there are some that, I think, even an experienced JavaScript developer will find difficult. However, among these questions there are also those for which it is sufficient to have basic knowledge to answer. There is a Russian translation in the repository, but, to put it mildly, it leaves much to be desired, so most of the answers (explanations) had to be translated again.
It should be noted that the explanations (answers) provided do not always fully reveal the essence of the problem. This is due to the form of the project - it is a checklist, not a tutorial. The answers are rather a hint for further searches on MDN orJavascript.ru . However, many of the explanations contain comprehensive answers.
Despite the fact that the code has been tested many times, no one is immune from errors, of course, except for those who do nothing. Therefore, if you find errors, typos, inaccuracies, incorrect wording, etc., as well as if you want to improve the translation, please write in a personal, I will be grateful (activity on GitHub is also encouraged).
Actually, that's all I wanted to say as a preface.
rules
The rules are simple: 50 questions, 3-4 possible answers, rating: number of correct and incorrect answers, progress: number and number of questions.
Based on the results, the percentage of correct answers is determined and a conclusion is made about the level of JavaScript proficiency: more than 80% is excellent, more than 50% is not bad, less than 50% ... well, you understand.
An explanation is attached to each question. If the answer is incorrect, this explanation is disclosed.
Due to the fact that the number of correct and incorrect answers, as well as the serial number of the question, are recorded in the local storage, you have the opportunity to pause, take a break and at any time continue from the place where you left off.
Let's move on from the quiz itself.
Quiz
The project code is here .
We share the results in the comments.
Mechanics
A few words about how the quiz is implemented for those who are interested.
The markup looks like this:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>200+ JavaScript</title>
<!-- -->
<link href="https://fonts.googleapis.com/css2?family=Ubuntu&display=swap" rel="stylesheet">
<!-- -->
<link rel="stylesheet" href="style.css">
<!-- "" -->
<script type="module" src="script.js"></script>
</head>
<body></body>
Add minimal styles:
CSS:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Ubuntu, sans-serif;
font-size: 1em;
text-align: center;
letter-spacing: 1.05px;
line-height: 1.5em;
color: #111;
user-select: none;
}
@media (max-width: 512px) {
* {
font-size: .95em;
}
}
html {
position: relative;
}
body {
padding: 1em;
min-height: 100vh;
background: radial-gradient(circle, skyblue, steelblue);
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
}
h1 {
margin: .5em;
font-size: 1.05em;
}
output {
margin: .5em;
display: block;
}
.score {
font-size: 1.25em;
}
form {
text-align: left;
}
form p {
text-align: left;
white-space: pre;
}
form button {
position: relative;
left: 50%;
transform: translateX(-50%);
}
button {
margin: 2em 0;
padding: .4em .8em;
outline: none;
border: none;
background: linear-gradient(lightgreen, darkgreen);
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
font-size: .95em;
cursor: pointer;
transition: .2s;
}
button:hover {
color: #eee;
}
label {
cursor: pointer;
}
input {
margin: 0 10px 0 2em;
cursor: pointer;
}
details {
font-size: .95em;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 90%;
background: #eee;
border-radius: 4px;
cursor: pointer;
}
details h3 {
margin: .5em;
}
details p {
margin: .5em 1.5em;
text-align: justify;
text-indent: 1.5em;
}
.right {
color: green;
}
.wrong {
color: red;
}
Assets are an array of objects, where each object has properties question (question), answers (answers), rightAnswer (correct answer) and explanation (explanation):
[
{
question: `
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
`,
answers: `
A: Lydia undefined
B: Lydia ReferenceError
C: ReferenceError 21
D: undefined ReferenceError
`,
rightAnswer: `D`,
explanation: `
name var. , name . Name undefined , , Lydia. name, , undefined. , let ( const), , var, . . " ". , JavaScript ReferenceError.
`
},
...
]
Main script:
JavaScript
// -
import assets from './assets.js'
// IIFE
;((D, B) => {
// -
const title = D.createElement('h1')
B.append(title)
// :
const score = D.createElement('output')
score.className = 'score'
B.append(score)
// :
const progress = D.createElement('output')
progress.className = 'progress'
B.append(progress)
// ,
const div = D.createElement('div')
B.append(div)
//
// 0
let rightAnswers = +localStorage.getItem('rightAnswers') || 0
let wrongAnswers = +localStorage.getItem('wrongAnswers') || 0
//
// 0
let i = +localStorage.getItem('i') || 0
//
showQuestion()
//
updateScoreAndProgress()
function showQuestion() {
//
// , ,
//
if (i === assets.length) {
return showResult()
}
// - -
const titleText = {
4: ` ?`,
9: ` ?`,
12: ` `,
13: ` ?`,
14: ` ?`,
20: ` sum?`,
21: ` cool_secret?`,
23: ` ?`,
25: ` : this`,
27: ` ?`,
29: ` ?`,
30: ` event.target ?`,
33: ` ?`,
34: ` ""?`,
38: ` JavaScript `,
39: ` ?`,
40: ` ?`,
41: ` setInterval?`,
42: ` ?`,
48: ` num?`,
49: ` ?`
}
title.textContent = titleText[i] || ` ?`
// - ,
// , ,
const {
question,
rightAnswer,
explanation
} = assets[i]
// - input type="radio",
// ( - \n)
// - ,
// slice(1, -1),
//
const answers = assets[i].answers
.split('\n')
.slice(1, -1)
.map(i => i.trim())
// HTML-
const template = `
<form action="#">
<p><em>:</em><br> ${question}</p>
<p><em> :</em></p><br>
${answers.reduce((html, item) => html += `<label><input type="radio" name="answer" value="${item}">${item}</label><br>`, '')}
<button type="submit"></button>
</form>
<details>
<summary> </summary>
<section>
<h3> : ${rightAnswer}</h3>
<p>${explanation}</p>
</section>
</details>`
//
div.innerHTML = template
//
const form = div.querySelector('form')
//
form.querySelector('input').setAttribute('checked', '')
//
form.addEventListener('submit', ev => {
//
ev.preventDefault()
//
const chosenAnswer = form.querySelector('input:checked').value.substr(0, 1)
//
checkAnswer(chosenAnswer, rightAnswer)
})
}
function checkAnswer(chosenAnswer, rightAnswer) {
//
let isRight = true
// ,
// ,
// ,
// ,
//
// false
if (chosenAnswer === rightAnswer) {
rightAnswers++
localStorage.setItem('rightAnswers', rightAnswers)
} else {
wrongAnswers++
localStorage.setItem('wrongAnswers', wrongAnswers)
isRight = false
}
//
const button = div.querySelector('button')
//
if (isRight) {
//
title.innerHTML = `<h1 class="right">!</h1>`
//
button.disabled = true
//
//
//
const timer = setTimeout(() => {
updateScoreAndProgress()
showQuestion()
clearTimeout(timer)
}, 1000)
//
} else {
//
title.innerHTML = `<h1 class="wrong">!</h1>`
//
div.querySelectorAll('input').forEach(input => input.disabled = true)
//
div.querySelector('details').setAttribute('open', '')
//
button.textContent = ''
//
//
//
button.addEventListener('click', () => {
updateScoreAndProgress()
showQuestion()
}, {
once: true
})
}
//
i++
//
localStorage.setItem('i', i)
}
function updateScoreAndProgress() {
//
score.innerHTML = `<span class="right">${rightAnswers}</span> - <span class="wrong">${wrongAnswers}</span>`
//
progress.innerHTML = `${i + 1} / ${assets.length}`
}
function showResult() {
//
const percent = (rightAnswers / assets.length * 100).toFixed()
//
let result
//
// result
if (percent >= 80) {
result = ` ! JavaScript.`
} else if (percent > 50) {
result = ` , .`
} else {
result = `, JavaScript.`
}
//
B.innerHTML = `
<h1> </h1>
<div>
<p> : <span class="right">${rightAnswers}</span></p>
<p> : <span class="wrong">${wrongAnswers}</span></p>
<p> : ${percent}</p>
<p>${result}</p>
<button></button>
</div>
`
//
//
// ,
//
B.querySelector('button').addEventListener('click', () => {
localStorage.clear()
location.reload()
}, {
once: true
})
}
})(document, document.body)
Thank you for attention.