📚 ECMAScript 核心语法课件(Node.js/React 环境)
1. 变量与作用域
变量声明方式
-
var
:函数作用域,存在变量提升(hoisting)javascriptconsole.log(a); // undefined(变量提升) var a = 10;
-
let
:块级作用域,无变量提升javascript// console.log(b); // 报错(暂时性死区) let b = 20;
-
const
:块级作用域,声明时必须初始化,不可重新赋值javascriptconst c = 30; // c = 40; // 报错
作用域类型
- 全局作用域:在函数外声明,全局可访问
- 函数作用域 :
var
声明的变量在函数内有效 - 块级作用域 :
let
/const
在{}
内有效(如if
、for
语句)
示例对比
javascript
// var 的变量提升
function testVar() {
console.log(x); // undefined
var x = 1;
}
// let 的块级作用域
if (true) {
let y = 2;
}
// console.log(y); // 报错:y is not defined
2. 数据类型
基本数据类型(7种)
undefined
:未定义的值null
:空值boolean
:true
/false
number
:整数/浮点数(包括NaN
、Infinity
)
javascript
let num = 3.14;
let nan = NaN; // 非数字值
string
:字符串(可用单/双引号或模板字符串)
javascript
let name = "Alice";
let greeting = `Hello, ${name}!`; // 模板字符串
symbol
:唯一值(ES6+)
javascript
let sym = Symbol("id");
bigint
:大整数(ES2020+)
javascript
let bigNum = 9007199254740991n;
引用数据类型
-
object
:对象、数组、函数等javascriptlet obj = { key: "value" }; let arr = [1, 2, 3]; function func() {}
类型检测方法
-
typeof
:检测基本类型(注意typeof null === "object"
) -
instanceof
:检测引用类型(如arr instanceof Array
) -
Object.prototype.toString.call()
:精确检测所有类型javascriptObject.prototype.toString.call([]); // "[object Array]"
3. 运算符与表达式
算术运算符
-
+
、-
、*
、/
、%
、**
(指数)javascriptconsole.log(2 ** 3); // 8
比较运算符
-
==
(宽松相等)、===
(严格相等)javascript"5" == 5; // true "5" === 5; // false
逻辑运算符
-
&&
(与)、||
(或)、!
(非)javascriptlet value = null || "default"; // "default"
赋值运算符
-
=
、+=
、-=
、*=
等javascriptlet count = 10; count += 5; // 15
其他运算符
-
三元运算符:
condition ? expr1 : expr2
javascriptlet result = score > 60 ? "及格" : "不及格";
-
可选链(
?.
):避免访问null
/undefined
属性(ES2020+)javascriptlet name = user?.profile?.name; // 安全访问
4. 流程控制
条件语句
-
if...else
:javascriptif (score > 90) { console.log("优秀"); } else if (score > 60) { console.log("及格"); } else { console.log("不及格"); }
-
switch
:javascriptswitch (color) { case "red": console.log("红色"); break; default: console.log("其他颜色"); }
循环语句
-
for
:javascriptfor (let i = 0; i < 5; i++) { console.log(i); }
-
while
/do...while
:javascriptlet i = 0; while (i < 5) { console.log(i); i++; }
-
for...of
(遍历可迭代对象,如数组):javascriptlet arr = [1, 2, 3]; for (let item of arr) { console.log(item); }
跳转语句
break
:退出循环continue
:跳过本次循环return
:函数返回值
💡 教学建议
- 结合 Node.js 环境演示 :使用
node
命令直接运行示例代码,观察结果。 - 对比 TypeScript:在讲解时可提示 TS 的增强点(如类型注解、静态检查)。
- 联系 React 开发 :
- 组件状态(
useState
)常用let
/const
声明。 - Props 传递涉及对象类型检测。
- 条件渲染需熟练运用
&&
、三元运算符。
- 组件状态(
- 常见陷阱强调 :
var
的变量提升与作用域问题。NaN
的特殊性(NaN !== NaN
)。- 浮点数精度问题(如
0.1 + 0.2 !== 0.3
)。
好的,以下是针对【函数、对象与面向对象、集合、模块化】的 ECMAScript 课件内容和知识点举例,结合了现代 ES6+ 语法和 React 开发中的常见模式。
📘 ECMAScript 核心概念进阶课件
1. 函数
函数定义与提升
-
函数声明 :整体提升,可在定义前调用
javascriptconsole.log(add(2, 3)); // 5 (函数提升) function add(a, b) { return a + b; }
-
函数表达式 :仅变量提升,不可提前调用
javascript// console.log(multiply(2, 3)); // 报错 const multiply = function(a, b) { return a * b; };
箭头函数 (ES6+)
-
语法简洁,无自身
this
,继承自外层作用域javascript// 传统函数 [1, 2, 3].map(function(x) { return x * x; }); // 箭头函数 [1, 2, 3].map(x => x * x); // [1, 4, 9] // React 中的使用:避免 this 绑定问题 const MyComponent = () => <div>Hello World</div>;
默认参数与剩余参数
-
默认参数 :为参数提供默认值
javascriptfunction greet(name = "Guest", greeting = "Hello") { return `${greeting}, ${name}!`; } console.log(greet()); // "Hello, Guest!"
-
剩余参数 :将不定数量的参数表示为数组
javascriptfunction sum(...numbers) { return numbers.reduce((acc, curr) => acc + curr, 0); } console.log(sum(1, 2, 3, 4)); // 10
2. 对象与面向对象
对象字面量增强 (ES6+)
-
属性简写 :变量名直接作为属性名
javascriptconst name = "Alice"; const age = 25; // ES5 const personOld = { name: name, age: age }; // ES6+ const personNew = { name, age }; // { name: "Alice", age: 25 }
-
方法简写 :省略
function
关键字javascriptconst person = { name: "Bob", // ES5 sayHello: function() { console.log("Hello"); }, // ES6+ sayHi() { console.log("Hi"); } };
-
计算属性名 :使用
[]
动态定义属性名javascriptconst propKey = "firstName"; const person = { [propKey]: "John", // firstName: "John" [`get${propKey}`]() { return this[propKey]; } // getFirstName() };
类 (Class) 语法 (ES6+)
-
class
定义类,constructor
定义构造函数,extends
实现继承javascriptclass Person { constructor(name, age) { this.name = name; this.age = age; } // 方法定义在原型上 greet() { console.log(`Hello, my name is ${this.name}`); } // 静态方法 static describe() { console.log("This is a Person class"); } } class Student extends Person { constructor(name, age, grade) { super(name, age); // 调用父类 constructor this.grade = grade; } study() { console.log(`${this.name} is studying`); } } const alice = new Student("Alice", 22, "A"); alice.greet(); // "Hello, my name is Alice" Student.describe(); // "This is a Person class"
3. 集合
Set
-
成员值唯一,无重复
javascriptconst numbers = [1, 2, 2, 3, 4, 4, 5]; const uniqueNumbers = new Set(numbers); // Set(5) {1, 2, 3, 4, 5} console.log([...uniqueNumbers]); // [1, 2, 3, 4, 5] (转数组) // 常用方法 const set = new Set(); set.add(1).add(2).add(3); // 添加 console.log(set.has(2)); // true (检查是否存在) set.delete(2); // 删除 console.log(set.size); // 2 (获取大小) set.clear(); // 清空
Map
-
键值对集合,键可以是任意类型
javascriptconst map = new Map(); const keyObj = { id: 1 }; map.set(keyObj, "value associated with object"); // 设置键值对 map.set("name", "Alice"); console.log(map.get(keyObj)); // "value associated with object" (获取值) console.log(map.has("name")); // true console.log(map.size); // 2 map.delete("name"); // 删除 // map.clear(); // 清空 // 遍历 for (let [key, value] of map) { console.log(key, value); }
WeakSet 与 WeakMap
-
弱引用,键必须是对象,不可枚举,无
size
属性,不易造成内存泄漏javascriptlet obj = { data: "test" }; const weakSet = new WeakSet(); weakSet.add(obj); const weakMap = new WeakMap(); weakMap.set(obj, "some value"); // 当 obj = null 时,垃圾回收机制会自动回收 weakSet 和 weakMap 中的记录
4. 模块化 (ES6 Module)
导出 (Export)
-
命名导出 :一个模块可导出多个[citation:10][citation:11]
javascript// math.js export const PI = 3.14159; export function square(x) { return x * x; } export class Calculator { add(a, b) { return a + b; } } // 或者最后统一导出 // export { PI, square, Calculator };
-
默认导出 :一个模块只能有一个[citation:10][citation:11]
javascript// logger.js const defaultLogger = { log: (msg) => console.log(`LOG: ${msg}`) }; export default defaultLogger;
导入 (Import)
-
导入命名导出 :[citation:10][citation:11]
javascript// main.js import { PI, square, Calculator } from './math.js'; console.log(PI);
-
导入默认导出 :[citation:10][citation:11]
javascriptimport logger from './logger.js'; // 名称可自定义 logger.log("Hello");
-
混合导入 :[citation:10][citation:11]
javascriptimport React, { Component } from 'react'; // React 默认导出,Component 是命名导出
-
动态导入 :按需加载[citation:10][citation:11]
javascript// 返回一个 Promise import('./module.js') .then(module => { module.doSomething(); }) .catch(err => { console.error("Module loading failed", err); }); // 或在 async 函数中使用 async function loadModule() { const module = await import('./module.js'); module.doSomething(); }
在 Node.js 和浏览器中使用
-
Node.js :在
package.json
中设置"type": "module"
,或使用.mjs
扩展名[citation:10][citation:11]json// package.json { "type": "module" }
-
浏览器 :使用
<script type="module">
标签[citation:11]html<script type="module" src="main.js"></script>
💡 教学提示与最佳实践
-
函数选择:
- 优先使用箭头函数 ,尤其在需要固定
this
的场景(如 React 事件处理、定时器)。 - 对于需要自身
this
(如对象方法)或需要提升的函数,使用函数声明。
- 优先使用箭头函数 ,尤其在需要固定
-
面向对象编程:
- 使用
class
语法让代码更清晰易读,更接近传统面向对象语言。 extends
和super
使继承变得简单。
- 使用
-
集合运用:
- 需要存储唯一值 时用
Set
。 - 需要键值对 且键可能为非字符串时用
Map
(优于普通对象)。 - 处理** DOM 节点**等对象且担心内存泄漏时,考虑
WeakMap
或WeakSet
。
- 需要存储唯一值 时用
-
模块化工程:
- ES6 Module 是现代 JavaScript 项目的标准模块化方案。
- 合理使用命名导出 和默认导出,保持模块职责单一。
- 动态导入可用于代码分割(Code Splitting),提升大型应用初始加载速度。
-
React 关联示例:
- 函数组件:大量使用箭头函数和默认导出。
javascript// React 函数组件 (通常默认导出) const Welcome = (props) => <h1>Hello, {props.name}</h1>; export default Welcome;
- 类组件 :使用
class
和extends Component
。
javascriptimport React, { Component } from 'react'; class Welcome extends Component { render() { return <h1>Hello, {this.props.name}</h1>; } } export default Welcome;
- Hooks:模块化导入。
javascriptimport React, { useState, useEffect } from 'react';