我的简单测试程序正确地加减数字。但是,我想把我的全局变量counter
变成一个局部变量。我无法从逻辑上理解如何做到这一点并保持程序运行。有没有办法定位counter
,使其只能从addNumber
或subtractNumber
闭包访问?非常感谢!
'use strict';
var counter;
counter = 0;
document.getElementsByClassName('box')[0].addEventListener('click', addNumber);
document.getElementsByClassName('box')[1].addEventListener('click', subtractNumber);
document.getElementsByClassName('box_answer')[0].textContent = 'The answer is ' +counter;
function calculateNumber(x) {
counter += x;
displayNumber();
}
function displayNumber() {
document.getElementsByClassName('box_answer')[0].textContent = 'The answer is ' +counter;
}
function addNumber() {
calculateNumber(1);
}
function subtractNumber() {
calculateNumber(-1);
}
body {
margin: 0;
padding: 0;
font-size: 2rem;
font-family: sans-serif;
}
.box {
margin-bottom: 20px;
padding: 10px;
color: white;
background-color: blue;
}
.box_answer {
padding: 10px;
background-color: orange;
}
<div class="box">addNumber</div>
<div class="box">subtractNumber</div>
<div class="box_answer"></div>
实现这一点的方法是将所有代码从全局范围中取出,无论如何都应该努力做到这一点。这通常是通过将所有代码包装在立即调用函数表达式中来完成的。
此外,您不需要单独的加法和减法函数。只需让每个点击事件处理程序调用一个函数,并将要使用的值传递给该函数。
最后,除非您有一个特定的用例,否则请避免像以下这样的DOM API调用:
- .getElementsByName()
- .getElementsByTagName()
- .getElementsByClassName()
因为它们都返回"活动"节点列表,这会导致每次在代码中引用节点列表时,都会重新扫描整个DOM以查找匹配的元素。这可能会带来戏剧性的表演冲击。相反,使用更现代的:
- .querySelector()
- .querySelectorAll()
当然还有:
- .getElementById()
这三个API将处理您的大部分DOM查询需求。
(function(){
'use strict';
// .getElementsByClassName returns a "live" node list, which is not recommended
// for most use cases because it requires re-scanning the DOM every time the node
// list is used. querySelector() and .querySelectorAll() are the modern successors
// to that.
var answer = document.querySelector('.box_answer');
// Find box by its unique class (or id) so that you don't scan the entire DOM only to
// throw away all found elements but the one you want:
document.querySelector('.box.add').addEventListener('click', function() { doMath(1); });
document.querySelector('.box.subtract').addEventListener('click', function() { doMath(-1); });
var counter = 0;
function doMath(x) {
counter += x;
displayNumber();
}
function displayNumber() {
answer.textContent = 'The answer is ' + counter;
}
})();
body {
margin: 0;
padding: 0;
font-size: 2rem;
font-family: sans-serif;
}
.box {
margin-bottom: 20px;
padding: 10px;
color: white;
background-color: blue;
cursor:pointer; /* Change pointer to let user know they can click */
/* Prevent text in element from being selected. Helps when lots of clicking happens. */
user-select:none;
}
.box_answer {
padding: 10px;
background-color: orange;
}
<div class="box add">addNumber</div>
<!-- Give each box a different class (or id) to differentiate one from the other. -->
<div class="box subtract">subtractNumber</div>
<div class="box_answer">The answer is:</div>
您可以将所有变量和函数移动到IIFE(立即调用的函数表达式)的内部。
'use strict';
void function () {
function calculateNumber(x) {
counter += x;
displayNumber();
}
function displayNumber() {
document.getElementsByClassName('box_answer')[0].textContent = 'The answer is ' +counter;
}
function addNumber() {
calculateNumber(1);
}
function subtractNumber() {
calculateNumber(-1);
}
var counter = 0;
document.getElementsByClassName('box')[0].addEventListener('click', addNumber);
document.getElementsByClassName('box')[1].addEventListener('click', subtractNumber);
document.getElementsByClassName('box_answer')[0].textContent = 'The answer is ' + counter;
}();
body { margin: 0; padding: 0; font-size: 2rem; font-family: sans-serif; }
.box { margin-bottom: 20px; padding: 10px; color: white; background-color: blue; }
.box_answer { padding: 10px; background-color: orange; }
<div class="box">addNumber</div>
<div class="box">subtractNumber</div>
<div class="box_answer"></div>