跳到主要内容JavaScript 基础:变量、DOM、表单与定时器 | 极客日志JavaScriptNode.js大前端
JavaScript 基础:变量、DOM、表单与定时器
这份笔记整理了 JavaScript 的几个基础点:变量声明里为什么更推荐用 let 和 const,而不是 var;DOM 元素如何通过 querySelector、getElementById 等方式获取;文本、属性、classList、style、表单值和 data-* 自定义属性分别怎么读写;最后还补了 setTimeout 和 setInterval 的用法,以及定时器受主线程影响、需要保存 id 并及时清除这些实际开发里常踩的点。
星河入梦12 浏览 变量声明
JavaScript 里声明变量,常用的是 let 和 const。更早的时候也会见到 var,但现在多数场景不再推荐。
var 的问题比较直接:它允许重复声明,还有变量提升。也就是说,变量看起来像是'先用后声明',实际拿到的往往是 undefined。再加上它只有函数作用域或全局作用域,不受块级作用域限制,写在 if、for 里也可能跑到外面去,排查起来很烦。
let 解决了这类老问题:不允许重复声明,也有块级作用域,但不能在声明前使用。
const 也有块级作用域,而且必须初始化。一般我会优先用 const,只有确实需要重新赋值时再换成 let。var 这类写法,除非是在读旧代码,不然没必要再碰。
DOM 树和 DOM 对象
获取 DOM 元素
在页面里找元素,document.querySelector('selector') 通常最顺手,返回第一个匹配项;document.querySelectorAll('selector') 会返回所有匹配项,结果是静态 NodeList,复杂选择器也能用。
类选择器
const firstItem = document.querySelector('.list-item');
const allItems = document.querySelectorAll('.list-item');
id 选择器
用 # 前缀匹配元素的 id。
const name = document.querySelector('#username');
标签选择器
直接写标签名就行。
const body = document.querySelector('body');
其它方式
通过 ID 获取元素
document.getElementById('id') 传入元素 ID,返回第一个匹配元素,不存在就返回 null。
const element = document.getElementById('header');
通过类名获取元素
返回动态 HTML 集合,里面是所有匹配的类名元素。
document.getElementsByClassName('class')
const elements = document.getElementsByClassName('menu-item');
通过标签名获取元素
document.getElementsByTagName('tag') 返回所有匹配标签的动态 HTML 集合。
const divs = document.getElementsByTagName('div');
DOM 元素内容及属性的修改
DOM 元素内容修改
常用的是 innerHTML、textContent 和 innerText。
innerHTML 会把 HTML 标签当成结构解析,适合插入带格式的内容;textContent 只当纯文本处理;innerText 会受 CSS 影响,通常更贴近页面'看见的文本'。
const element = document.getElementById('target');
element.innerHTML = '<strong>加粗文本</strong>';
element.textContent = '<strong>纯文本显示</strong>';
DOM 属性修改
标准 HTML 属性可以直接通过对象属性改,也可以用 setAttribute。自定义属性一般用 dataset 或 setAttribute。删属性则用 removeAttribute。
const img = document.querySelector('img');
img.src = 'new-image.jpg';
img.setAttribute('alt', '新图片描述');
img.setAttribute('data-custom', 'value');
const customValue = img.dataset.custom;
批量修改多个元素
querySelectorAll 拿到节点列表后,直接用 for 循环处理就行。这个写法不花哨,但够稳。
样式类名操作
classList 是我更愿意用的方式,add、remove、toggle、contains 都很清晰。相比直接拼 className 字符串,它不容易把原有类名弄丢。
add(className):添加一个或多个类名,重复添加不会报错
remove(className):删除一个或多个类名,不存在也不会报错
toggle(className):有就删,没有就加
contains(className):判断是否包含某个类名,返回布尔值
const box = document.getElementById('box');
box.classList.add('active');
box.classList.remove('inactive');
box.classList.toggle('visible');
box.className = 'new-class';
替换类名
classList.replace(oldClass, newClass) 适合直接切换样式类型。
box.classList.replace('big', 'small');
console.log(box.className);
为什么更推荐 classList
直接改 className 往往要自己拼字符串,简单场景还能忍,复杂一点就容易出错。
box.className = 'active';
box.className = box.className + ' active';
box.classList.add('active');
注意事项
classList 只管类名,不管 id、data-* 这类属性。
- 传参时不要带
.,要写 add('active'),不是 add('.active')。
add、remove 都支持多个类名,比如 add('a', 'b', 'c')。
- 现代浏览器都支持,IE10+ 也没问题,日常开发够用了。
检查类名是否存在
if (element.classList.contains('active')) {
console.log('Element has active class');
}
表单元素值操作
input、select 这类表单控件,一般直接读写 value。复选框和单选按钮则看 checked。
const input = document.getElementById('username');
input.value = '新用户';
const checkbox = document.getElementById('agree');
checkbox.checked = true;
使用 style 属性修改样式
需要临时改样式时,可以直接操作元素的 style。这种方式适合动态变化,或者临时覆盖内联样式。
element.style.property = value;
<!DOCTYPE html>
<html>
<body>
<div>测试盒子</div>
<button onclick="changeStyle()">修改样式</button>
<script>
const box = document.getElementById('myBox');
function changeStyle() {
box.style.backgroundColor = 'red';
box.style.width = '200px';
box.style.height = '200px';
box.style.borderRadius = '10px';
box.style.color = 'white';
box.style.fontSize = '16px';
}
</script>
</body>
</html>
color:修改文本颜色
backgroundColor:修改背景颜色
fontSize:修改字体大小
width / height:修改元素宽高
display:控制显示方式,比如 none 隐藏元素
注意事项
- CSS 属性名要转成驼峰,比如
font-size 写成 fontSize,border-top 写成 borderTop。
- 数值类样式一般要带单位,比如
px、rem,不然不会生效。
style 写进去的是行内样式,优先级比类样式高,!important 例外。
- 想恢复默认样式,可以把属性值设为空字符串,比如
box.style.backgroundColor = ''。
通过 JavaScript 修改样式
这和上面那段其实是一回事,只是写法更直白:先拿到元素,再改 style。
const element = document.getElementById("myElement");
element.style.color = "red";
element.style.fontSize = "16px";
获取表单里的值
方法 1:通过元素 ID 直接获取
这是最省事的写法。给表单元素加上唯一 id,然后通过 document.getElementById() 取值。
<!DOCTYPE html>
<html>
<body>
<form>
<label>用户名:</label><input type="text"><br>
<label>密码:</label><input type="password"><br>
<label>性别:</label>
<input type="radio" name="gender" value="男">男
<input type="radio" name="gender" value="女">女<br>
<button type="button" onclick="getFormValueById()">获取值</button>
</form>
<script>
function getFormValueById() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const male = document.getElementById('male');
const female = document.getElementById('female');
const gender = male.checked ? male.value : female.checked ? female.value : '未选择';
console.log('用户名:', username);
console.log('密码:', password);
console.log('性别:', gender);
}
</script>
</body>
</html>
方法 2:通过表单对象获取
如果表单项比较多,直接从表单对象里按 name 取,会更顺手一点。
<!DOCTYPE html>
<html>
<body>
<form>
<label>用户名:</label><input type="text" name="username"><br>
<label>爱好:</label>
<input type="checkbox" name="hobby" value="读书">读书
<input type="checkbox" name="hobby" value="运动">运动
<input type="checkbox" name="hobby" value="游戏">游戏<br>
<label>城市:</label>
<select name="city">
<option>请选择</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
</select><br>
<button type="button" onclick="getFormValueByForm()">获取值</button>
</form>
<script>
function getFormValueByForm() {
const form = document.getElementById('userForm');
const username = form.username.value;
const city = form.city.value;
const hobbies = [];
form.hobby.forEach(item => {
if (item.checked) {
hobbies.push(item.value);
}
});
console.log('用户名:', username);
console.log('城市:', city);
console.log('爱好:', hobbies);
}
</script>
</body>
</html>
H5 自定义属性 data-
一、如何定义 data-* 自定义属性
自定义属性要以 data- 开头,后面可以接任意命名。实际写的时候,建议小写配连字符,可读性最好。
<!DOCTYPE html>
<html>
<body>
<div>用户信息</div>
<ul>
<li>智能手机</li>
<li>笔记本电脑</li>
</ul>
<button>操作按钮</button>
</body>
</html>
二、在 JavaScript 中操作自定义属性
常见做法有两种,实际开发里我更倾向于 dataset,语义清楚,也更贴近 HTML5 的设计。
方式 1:使用 dataset
dataset 会把所有 data-* 属性收进来,读取时会自动去掉 data- 前缀;带连字符的命名也会转成驼峰。它读出来的值都是字符串,数字或布尔值要自己转一下。另外,别拿它存密码这类敏感信息,控制台里看得到。
<script>
const userDiv = document.getElementById('user');
console.log(userDiv.dataset.id);
const btn = document.querySelector('button');
console.log(btn.dataset.userStatus);
console.log(btn.dataset.userRole);
userDiv.dataset.name = '张三';
userDiv.dataset.age = 25;
console.log(userDiv.dataset.name);
const productLi = document.querySelector('li');
for (let key in productLi.dataset) {
console.log(key + ': ' + productLi.dataset[key]);
}
delete userDiv.dataset.age;
console.log(userDiv.dataset.age);
</script>
注意事项
定时器——间歇函数
JavaScript 里常见的两个定时器是 setTimeout() 和 setInterval(),都属于 window 对象。一个负责延时一次执行,一个负责按固定间隔重复执行。
1. setTimeout():一次性延时执行
setTimeout() 用来指定一段时间后执行一次函数,执行完就结束。
let timerId = setTimeout(callback, delay, param1, param2, ...);
callback 是延时后执行的函数;delay 是毫秒数;后面的参数会原样传给回调函数;timerId 是定时器标识,后面清除它要靠这个值。
<!DOCTYPE html>
<html>
<body>
<button onclick="stopMyTimeout()">停止延时任务</button>
<script>
const timer1 = setTimeout(() => {
alert('3秒到了!');
}, 3000);
const timer2 = setTimeout((name, age) => {
console.log(`你好${name},年龄${age}`);
}, 2000, '张三', 25);
function stopMyTimeout() {
clearTimeout(timer1);
console.log('延时任务已停止');
}
</script>
</body>
</html>
2. setInterval():周期性重复执行
setInterval() 会每隔一段时间执行一次,直到你手动清掉它。
let intervalId = setInterval(callback, delay, param1, param2, ...);
参数含义和 setTimeout() 基本一致,区别只在于回调会重复触发。
<!DOCTYPE html>
<html>
<body>
<p>倒计时:<span>10</span> 秒</p>
<button onclick="stopMyInterval()">停止倒计时</button>
<script>
let count = 10;
const countSpan = document.getElementById('count');
const intervalId = setInterval(() => {
count--;
countSpan.textContent = count;
if (count <= 0) {
clearInterval(intervalId);
alert('倒计时结束!');
}
}, 1000);
function stopMyInterval() {
clearInterval(intervalId);
countSpan.textContent = '已停止';
}
</script>
</body>
</html>
二、关键注意事项
1. 定时器不是绝对准时
JavaScript 是单线程,定时器里的 delay 只是'最早多久后可以执行',不是精确到点就跑。主线程忙的时候,比如碰上复杂计算,定时器只能等它空下来。
setTimeout(() => {
console.log('1秒到了?');
}, 1000);
alert('请等待5秒后关闭');
2. 记得清除定时器
页面卸载前或者组件销毁前,没必要继续跑的定时器最好清掉。否则就是白白占着资源,有时还会留下奇怪的副作用。
清除定时器的前提是先保存 timerId,匿名写法后面没法收拾。
setTimeout(() => {}, 1000);
const timerId = setTimeout(() => {}, 1000);
clearTimeout(timerId);
setTimeout 适合一次性的延时任务,停止它用 clearTimeout(timerId);setInterval 适合轮询和倒计时,停止它用 clearInterval(intervalId)。它们都不是精确计时,delay 只是最小等待时间。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online