基础
变量
- var 变量
引入作用域概念: - let 可变变量
- const 不可变变量
函数
箭头函数
// ES5
var x = function(x, y) {
return x * y;
}
// ES6
const x = (x, y) => x * y;
!箭头函数没有this
闭包
保护函数的私有变量
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
//让counter只能被add访问,并且数值会被记住
DOM
HTML
document.getElementById("p1").innerHTML="新文本!";
document.getElementById("image").src="landscape.jpg";
CSS
document.getElementById("p2").style.color="blue";
# HTML DOM事件
- onclick
- onload/onunload 进入/离开页面
- onchange 改变输入
- onmouseover/onmouseout
Eventlistener
JavaScript从HTML标记中分离开来,可读性更强
//添加
document.getElementById("myBtn").addEventListener("click", displayDate);
//移除
element.removeEventListener("mousemove", myFunction);
DOM元素
var para = document.createElement("p");
var node = document.createTextNode("这是一个新的段落。");
para.appendChild(node);
var element = document.getElementById("div1"); element.appendChild(para);
现代JS(ES6+)关键特性
解构赋值
从数组或对象中提取值,并直接赋值给独立的变量
- 对象解构 const { prop1, prop2 } = obj;
- 数组解构const [first, second] = arr;
- 参数解构function MyComponent({ name, age }) {...}`
模版字符串
使用反引号`定义的字符串,可以嵌入表达式和多行文本
- 嵌入表达式${expression}
- 多行字符串
扩展语法
使用 ...操作符,展开数组或对象的元素/属性。用于集合的复制、合并、参数传递等。
数组扩展
// 数组合并 (创建新数组)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
const combinedWithExtra = [0, ...arr1, 3.5, ...arr2, 7]; // [0, 1, 2, 3, 3.5, 4, 5, 6, 7]
// 复制数组 (浅拷贝)
const arrCopy = [...arr1]; // [1, 2, 3] (修改 arrCopy 不会影响 arr1)
arrCopy.push(4);
console.log(arr1); // [1, 2, 3]
console.log(arrCopy); // [1, 2, 3, 4]
// 函数参数传递
function sum(a, b, c) { return a + b + c; }
const nums = [10, 20, 30];
console.log(sum(...nums)); // 60 (等同于 sum(10, 20, 30))
// 添加新元素 (避免 .push 修改原数组)
const newNumbers = [...numbers, 6]; // 添加末尾
const newNumbersFront = [0, ...numbers]; // 添加开头
对象扩展
const person = { name: 'Mike', age: 40 };
const address = { city: 'London', country: 'UK' };
// 对象合并 (创建新对象)
const userProfile = { ...person, ...address };
console.log(userProfile); // { name: 'Mike', age: 40, city: 'London', country: 'UK' }
// 添加新属性
const updatedPerson = { ...person, occupation: 'Developer' };
console.log(updatedPerson); // { name: 'Mike', age: 40, occupation: 'Developer' }
// 更新属性 (覆盖同名属性)
const updatedAge = { ...person, age: 41 }; // { name: 'Mike', age: 41 }
console.log(updatedAge);
// 覆盖 & 添加新属性
const withEmail = { ...person, age: 41, email: 'mike@example.com' };
console.log(withEmail); // { name: 'Mike', age: 41, email: 'mike@example.com' }
// 浅拷贝对象
const personCopy = { ...person }; // 修改 personCopy 不会影响 person
模块化
- export
- import
数组方法
map(): (用于将数据数组映射为React元素数组)filter(): 过滤数组元素find()/findIndex(): 查找元素/索引some()/every(): 检查元素是否满足条件forEach(): 遍历(避免在 JSX 中直接使用)reduce()/reduceRight(): 累积(功能强大,但优先级低于上述方法)slice(): 创建子数组副本concat(): 合并数组(可被扩展语法替代)
map()
创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
用途: 数据 -> 元素列表。生成组件列表。
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2); // [2, 4, 6]
const squared = numbers.map((num, index) => `Index ${index}: ${num * num}`); // 带索引
// React 渲染列表
const items = ['Apple', 'Banana', 'Cherry'];
const listItems = items.map((item) => <li key={item}>{item}</li>); // 生成 <li> 元素数组
// 在组件中:
return <ul>{listItems}</ul>; // 渲染列表
对象方法
异步编程
js是单线程语言,为了不阻塞主线程(UI渲染等),I/O操作(网络请求、文件读写、定时器)需要异步处理。
演进: Callback(回调地狱) -> Promise(链式调用) -> async/await(同步写法处理异步)。
回调函数 Callback
最简单的异步模式:将函数作为参数传递给另一个函数,在操作完成后调用它(作为回调)。
缺点: 嵌套回调过多导致“回调地狱”,难以阅读和维护。
function fetchData(callback) {
setTimeout(() => { // 模拟网络请求
callback('Data received!');
}, 1000);
}
fetchData((data) => {
console.log(data); // 1秒后输出 'Data received!'
// 如果这里再调用另一个异步函数,就会开始嵌套...
});
Promise
表示一个异步操作的最终完成(或失败)及其结果值。
优点: 链式调用,解决回调地狱。错误处理更集中。
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
resolve('Success data!');
} else {
reject(new Error('Failed to fetch!'));
}
}, 1000);
});
}
// 使用 Promise
fetchData()
.then(data => {
console.log('Got data:', data);
return processData(data); // processData 如果返回 Promise,可以继续 .then
})
.then(processed => {
console.log('Processed:', processed);
})
.catch(error => {
console.error('Error:', error.message);
});
async/await(语法糖,首选写法)
async: 声明一个函数是异步函数。该函数总是返回一个 Promise。如果函数内 return 一个非Promise值,async 函数会用Promise.resolve()将其包装成 Promise。await: 只能在async函数内部使用。它会暂停 async 函数的执行,等待一个 Promise 解决(成功或失败),然后返回解决后的值。- 优点: 代码扁平化,逻辑更清晰,错误处理用
try/catch(像处理同步错误一样)。
async function fetchUserData(userId) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`); // 等待fetch请求完成
if (!response.ok) { // 检查响应是否成功
throw new Error(`HTTP error! status: ${response.status}`);
}
const userData = await response.json(); // 等待解析JSON数据
console.log('User data:', userData);
return userData; // 返回解析后的数据 (会被包装在由async函数自动返回的Promise中)
} catch (error) {
console.error('Failed to fetch user:', error);
throw error; // 再次抛出错误,让调用此函数的代码可以通过 .catch 捕获
}
}
// 调用 async 函数
fetchUserData(123)
.then(data => console.log('Processed in then:', data))
.catch(err => console.error('Handled error:', err));
// 或者在另一个 async 函数中调用:
async function doSomething() {
const user = await fetchUserData(123);
// 拿到 user 后继续操作...
}