JavaScript速查手册
ES6+语法/数组/Promise/DOM速查表
✨ ES6+ 核心语法
块级作用域,无变量提升;默认 const,需要重新赋值才用 let。
const PI = 3.14;
let count = 0;
count += 1;
{
let x = 1; // 只在 {} 内有效
}
// const 保证绑定不可变,但对象/数组内容仍可修改
const arr = [1, 2];
arr.push(3);
更短的函数写法,且继承外层 this;但不能用作构造函数。
const add = (a, b) => a + b;
const square = x => x * x;
const log = () => console.log('hi');
const nums = [1, 2, 3].map(x => x * 2);
// 注意:箭头函数没有自己的 this / arguments
const obj = {
name: 'Tom',
hi() { setTimeout(() => console.log(this.name), 0); }
};
数组按位置、对象按键名;支持默认值、重命名、嵌套。
const {name, age} = {name: 'Tom', age: 18};
const {a: x, b: y = 10} = {a: 1}; // 重命名 + 默认值
const [first, second, ...rest] = [1, 2, 3, 4];
function print({name, age}) {
console.log(name, age);
}
const [[n], {id}] = [[9], {id: 1}]; // 嵌套解构
反引号可换行插值;... 展开数组/对象或收集剩余项。
const name = 'Tom';
const msg = `Hello, ${name}!
明年 ${age + 1} 岁`;
const merged = [...[1, 2], ...[3, 4]]; // [1,2,3,4]
const copy = {...{a: 1}, b: 2}; // {a:1,b:2}
Math.max(...[3, 1, 2]);
const [head, ...tail] = [1, 2, 3];
?. 避免深层判空崩溃;?? 只在 null/undefined 时取默认值。
function greet(name = '游客') { return `hi ${name}`; }
const city = user?.address?.city; // 任意一级为空返回 undefined
const first = list?.[0];
const fn = obj?.render?.(); // 方法存在才调用
const port = config.port ?? 8080; // 0 会被保留,只有 null/undefined 才回退
const name = input || 'default'; // 0/''/false 都会回退
import/export 静态加载;浏览器需 <script type="module">。
// math.js
export const PI = 3.14;
export function add(a, b) { return a + b; }
export default { version: '1.0' };
// app.js
import math, {PI, add as sum} from './math.js';
import * as M from './math.js';
const mod = await import('./math.js'); // 动态导入(返回 Promise)
遍历可迭代对象(数组、字符串、Map、Set);for...in 只用于对象键。
for (const v of [1, 2, 3]) console.log(v);
for (const ch of 'abc') console.log(ch);
for (const [i, v] of ['a', 'b'].entries()) {
console.log(i, v);
}
for (const key of Object.keys(obj)) {}
🔢 数组方法
函数式三件套,均返回新数组/值,不改原数组。
[1, 2, 3].map(x => x * 2); // [2,4,6]
[1, 2, 3, 4].filter(x => x > 2); // [3,4]
[1, 2, 3].reduce((sum, x) => sum + x, 0); // 6
const cart = [{p: 10, n: 2}, {p: 5, n: 3}];
cart.reduce((t, i) => t + i.p * i.n, 0); // 35
find 返回元素本身;some/every 返回布尔。
const users = [{id: 1, name: 'Tom'}, {id: 2, name: 'Amy'}];
users.find(u => u.id === 2); // {id:2,...}
users.findIndex(u => u.id === 2); // 1
[1, 2, 3].includes(2); // true
[1, 2, 3].some(x => x > 2); // true(任一满足)
[1, 2, 3].every(x => x > 0); // true(全部满足)
splice 原地改数组;slice 浅拷贝片段;concat/flat 不修改原数组。
const a = [1, 2, 3];
a.push(4); a.pop(); a.unshift(0); a.shift();
a.slice(1, 3); // [2,3] 原数组不变
a.splice(1, 1); // 从索引 1 删 1 个(原地)
a.splice(1, 0, 9); // 在索引 1 插入 9
[1, 2].concat([3, 4]); // [1,2,3,4]
[1, [2, [3]]].flat(2); // [1,2,3]
[1, 2, 3].join('-'); // "1-2-3"
默认按字符串排序,数字必须传比较函数;sort 会修改原数组。
[3, 1, 2].sort((a, b) => a - b); // [1,2,3]
[3, 1, 2].sort((a, b) => b - a); // [3,2,1]
users.sort((a, b) => a.age - b.age);
users.sort((a, b) => a.name.localeCompare(b.name, 'zh'));
const sorted = [...arr].sort((a, b) => a - b); // 不改原数组
Set 去重基础类型;对象数组按键去重用 Map。
[...new Set([1, 1, 2, 3, 3])]; // [1,2,3]
Array.from(new Set(['a', 'a', 'b']));
const uniq = [...new Map(
users.map(u => [u.id, u])
).values()]; // 按 id 去重
🧱 对象
键名与变量同名可省略;[] 中可放表达式作为键。
const name = 'Tom', age = 18;
const user = {name, age}; // {name:'Tom', age:18}
const key = 'email';
const obj = {
id: 1,
[key]: 'a@b.com',
[`${key}_verified`]: true,
hi() { return 'hi ' + this.name; } // 方法简写
};
entries 配合 Object.fromEntries 可做对象 map/filter。
const o = {a: 1, b: 2};
Object.keys(o); // ['a','b']
Object.values(o); // [1,2]
Object.entries(o); // [['a',1],['b',2]]
Object.fromEntries([['a', 1]]); // {a:1}
const doubled = Object.fromEntries(
Object.entries(o).map(([k, v]) => [k, v * 2])
);
扩展运算符合并对象;深拷贝优先 structuredClone。
const merged = Object.assign({}, {a: 1}, {b: 2});
const copy = {...user, age: 20};
const deep = structuredClone(user); // 现代浏览器/Node17+,支持嵌套
const deep2 = JSON.parse(JSON.stringify(user)); // 兼容写法(丢失函数/Date 等)
Object.freeze(user); // 冻结(浅)
for...in 会遍历原型链可枚举属性,建议配合 hasOwn 判断。
for (const key in obj) {
if (Object.hasOwn(obj, key)) {
console.log(key, obj[key]);
}
}
Object.entries(obj).forEach(([k, v]) => {
console.log(k, v);
});
🗺 Map / Set
键可以是任意类型(含对象),有序、有 size,频繁增删性能更好。
const m = new Map([['a', 1], ['b', 2]]);
m.set('c', 3).set('a', 10);
m.get('a'); // 10
m.has('x'); // false
m.delete('b');
m.size; // 2
for (const [k, v] of m) console.log(k, v);
new Map(Object.entries({a: 1})); // 普通对象 -> Map
自动去重;并集/交集/差集有内置方法(现代 JS)。
const s = new Set([1, 2, 2, 3]);
s.add(4); s.has(1); s.delete(2);
s.size;
[...s]; // [1,3,4]
const a = new Set([1, 2, 3]), b = new Set([2, 3, 4]);
a.union(b); // {1,2,3,4}
a.intersection(b); // {2,3}
a.difference(b); // {1}
⏳ Promise 与异步
链式调用;then 第二参数或 catch 处理拒绝。
const p = new Promise((resolve, reject) => {
setTimeout(() => resolve('done'), 100);
});
p
.then(v => console.log(v))
.catch(e => console.error(e))
.finally(() => console.log('无论成败'));
Promise.resolve(1).then(v => v + 1);
Promise.reject(new Error('x')).catch(e => e.message);
all 一个失败即失败;allSettled 等待全部结束并给出状态。
const results = await Promise.all([fetchA(), fetchB()]);
const first = await Promise.race([fetchA(), timeout(3000)]);
const all = await Promise.allSettled([p1, p2]);
// all -> [{status:'fulfilled', value}, {status:'rejected', reason}]
const ok = await Promise.any([p1, p2]); // 任一成功即返回
同步写法处理异步;try/catch 捕获错误。
async function getUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error('HTTP ' + res.status);
return await res.json();
} catch (e) {
console.error('请求失败', e);
}
}
const main = async () => {
const u = await getUser(1);
console.log(u);
};
互不依赖用 Promise.all 并行;有先后顺序才串行 await。
// 并行(快)
const [user, orders] = await Promise.all([
fetchUser(1),
fetchOrders(1)
]);
// 串行(慢但有依赖)
for (const id of [1, 2, 3]) {
await saveItem(id);
}
// 控制并发:每批 3 个
async function pool(items, limit, worker) {
const ret = [];
for (let i = 0; i < items.length; i += limit) {
ret.push(...await Promise.all(items.slice(i, i + limit).map(worker)));
}
return ret;
}
fetch 只有网络错误才 reject,HTTP 4xx/5xx 需检查 ok。
const res = await fetch('/api/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({user: 'tom', pwd: 'x'})
});
const data = await res.json();
// GET 查询参数
const q = new URLSearchParams({page: '1', size: '20'});
const r2 = await fetch(`/api/list?${q}`);
const text = await r2.text();
🌳 DOM 操作
querySelector 返回单个,querySelectorAll 返回 NodeList(可用 forEach)。
const el = document.querySelector('#app .title');
const lis = document.querySelectorAll('ul li');
document.getElementById('app');
document.getElementsByClassName('item');
el.closest('.card'); // 向上找最近的祖先
el.matches('.active'); // 是否匹配选择器
textContent 更安全;innerHTML 会解析 HTML,注意 XSS。
el.textContent = '纯文本';
el.innerHTML = '<b>注意 XSS</b>';
el.value; // 表单值
el.href; el.checked;
el.setAttribute('data-id', '9');
el.getAttribute('href');
el.hidden = true;
el.style.color = 'red';
classList 增删切换;CSS 变量也可读写。
el.classList.add('active');
el.classList.remove('active');
el.classList.toggle('active');
el.classList.contains('active');
el.style.setProperty('--h', '100px');
getComputedStyle(el).color;
DocumentFragment 批量插入可减少重排。
const li = document.createElement('li');
li.textContent = '新项目';
li.dataset.id = '5';
el.appendChild(li);
el.prepend(li);
el.before(li); el.after(li);
el.replaceWith(li);
li.remove();
const frag = document.createDocumentFragment();
[1, 2].forEach(n => {
const d = document.createElement('div');
d.textContent = n;
frag.appendChild(d);
});
list.appendChild(frag);
getBoundingClientRect 取相对视口位置。
const r = el.getBoundingClientRect();
r.top; r.left; r.width; r.height;
el.clientWidth; el.offsetHeight;
window.scrollY;
el.scrollIntoView({behavior: 'smooth'});
window.scrollTo({top: 0, behavior: 'smooth'});
🖱 事件
移除时必须传同一个函数引用;{ once: true } 只触发一次。
const onClick = e => console.log('click', e);
btn.addEventListener('click', onClick);
btn.removeEventListener('click', onClick);
el.addEventListener('click', fn, {once: true});
el.addEventListener('scroll', fn, {passive: true});
btn.onclick = null;
preventDefault 停默认行为,stopPropagation 停向上冒泡。
link.addEventListener('click', e => {
e.preventDefault(); // 不跳转
});
document.querySelector('form')
.addEventListener('submit', e => {
e.preventDefault(); // 表单不刷新页面
});
inner.addEventListener('click', e => {
e.stopPropagation(); // 外层 onClick 不触发
});
把监听挂在父容器,动态新增的子元素也生效,省监听器数量。
ul.addEventListener('click', e => {
const li = e.target.closest('li[data-id]');
if (!li || !ul.contains(li)) return;
console.log('点击了', li.dataset.id);
});
document.addEventListener('click', e => {
if (e.target.closest('.copy-btn')) doCopy();
});
target 实际触发源、currentTarget 监听者;键盘码与鼠标坐标。
input.addEventListener('keydown', e => {
e.key; // 'Enter'
e.code; // 'Enter'
e.ctrlKey; e.metaKey; e.shiftKey;
if (e.key === 'Enter') doSearch();
});
box.addEventListener('mousemove', e => {
e.clientX; e.clientY; // 相对视口
e.pageX; e.pageY; // 相对文档
});
🧰 常用技巧
setTimeout 一次、setInterval 循环,句柄用于取消。
const t = setTimeout(() => console.log('1秒后'), 1000);
clearTimeout(t);
const it = setInterval(() => console.log('tick'), 1000);
clearInterval(it);
requestAnimationFrame(() => {}); // 动画用这个,跟随屏幕刷新
防抖:停止后触发(搜索框);节流:间隔内最多一次(滚动)。
function debounce(fn, wait = 300) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), wait);
};
}
function throttle(fn, wait = 300) {
let last = 0;
return (...args) => {
const now = Date.now();
if (now - last >= wait) { last = now; fn(...args); }
};
}
input.addEventListener('input', debounce(onSearch, 300));
只能存字符串;JSON 序列化后存取对象,注意容量约 5MB。
localStorage.setItem('token', 'abc');
localStorage.getItem('token');
localStorage.removeItem('token');
const save = (k, v) => localStorage.setItem(k, JSON.stringify(v));
const load = k => {
try { return JSON.parse(localStorage.getItem(k)); }
catch { return null; }
};
sessionStorage.getItem('k'); // 会话级,关闭标签页清除
replacer 过滤字段,space 美化;循环引用会报错。
JSON.stringify({a: 1, b: 2});
JSON.stringify(obj, null, 2);
JSON.stringify(obj, ['id', 'name']); // 只保留这两个键
JSON.parse('{"a":1}');
JSON.parse(text, (k, v) => k === 'date' ? new Date(v) : v);
数组用 Array.isArray;NaN 用 Number.isNaN(全局 isNaN 会强转)。
typeof 'x'; // 'string'
typeof null; // 'object'(历史坑)
Array.isArray([]); // true
Number.isNaN(NaN);
Number.isInteger(3.0);
(3.14159).toFixed(2); // "3.14"(字符串,会四舍五入)
Math.round(3.5); Math.floor(3.9); Math.ceil(3.1);
parseInt('10px', 10); // 10
Number('12.5'); // 12.5
String(123); Boolean(0); // '123' / false
😶 没有匹配的条目,换个关键词试试
📖 使用说明
全程在浏览器本地运行。
操作步骤:
- 搜索或浏览分类条目;
- 查看语法与示例代码;
- 点击复制代码块。
💬 用户评论 (0)
还没有评论,快来抢沙发!