js 语法(保姆级教程)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在现代 Web 开发中,JavaScript(JS)作为核心语言,扮演着不可或缺的角色。无论是构建交互式网页、开发桌面应用,还是后端服务,掌握其语法基础都是开发者的核心能力。本文将从变量、函数、作用域到高级特性,系统性地解析 JS 语法的关键知识点,并通过实际案例帮助读者理解。无论你是编程新手还是有一定经验的开发者,都能在此找到适合自己的学习路径。
变量与数据类型:构建程序的基石
变量声明的三种方式
在 JS 中,变量通过 var
、let
和 const
声明。这三者的核心区别在于作用域和可变性:
var
:存在函数作用域,且会“变量提升”(即声明提前到函数顶部)。let
和const
:属于块级作用域(如{}
内),且不会变量提升。const
声明的变量不可重新赋值,但对象/数组内容可修改。
案例 1:比较 var
和 let
的作用域差异
function example() {
var a = 10;
if (true) {
let b = 20;
console.log(a); // 输出 10(var 的函数作用域)
console.log(b); // 输出 20(let 的块级作用域)
}
console.log(b); // 报错:b 未定义(超出块级作用域)
}
数据类型:原始类型与引用类型
JS 数据类型分为 原始类型(Primitive Types)和 引用类型(Reference Types):
- 原始类型:
number
、string
、boolean
、null
、undefined
、symbol
(ES6 新增)、bigint
。 - 引用类型:对象(如
Object
、Array
、Function
等),通过内存地址引用值。
比喻:原始类型像“书本的 ISBN 号”,直接存储具体值;而引用类型像“书架的编号”,指向存储内容的地址。
案例 2:理解值传递的差异
// 原始类型:值直接复制
let num1 = 5;
let num2 = num1; // 复制值为 5
num2 = 10;
console.log(num1); // 5(原始值不共享)
// 引用类型:地址共享
let arr1 = [1, 2];
let arr2 = arr1;
arr2.push(3);
console.log(arr1); // [1, 2, 3](修改通过地址关联)
函数:代码复用的核心
函数的三种定义方式
-
函数声明:
function add(a, b) { return a + b; }
函数提升(Hoisting)使其可在声明前调用。
-
函数表达式:
const multiply = function(a, b) { return a * b; };
需先定义后调用,无变量提升。
-
箭头函数(ES6):
const subtract = (a, b) => a - b;
简洁语法,无
this
绑定(继承外层this
)。
案例 3:箭头函数简化回调
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2); // 输出 [2,4,6]
参数默认值与剩余参数
ES6 引入了参数默认值和剩余参数语法,提升函数灵活性:
function greet(name = "Guest", ...args) {
console.log(`Hello, ${name}!`);
console.log("Additional args:", args);
}
greet("Alice", "Welcome", "to JS"); // 输出:Hello Alice! 和 ["Welcome", "to JS"]
作用域与闭包:理解变量的“可见性”
作用域类型
- 全局作用域:在函数外部声明的变量,全局可用。
- 函数作用域:由
function
定义的独立作用域。 - 块级作用域:通过
{}
和let/const
定义的局部作用域。
案例 4:作用域嵌套
let globalVar = "I'm global";
function outer() {
const outerVar = "Outer";
if (true) {
let innerVar = "Inner";
console.log(globalVar, outerVar, innerVar); // 全局、外层、内层变量均可见
}
console.log(innerVar); // 报错:innerVar 未定义(超出块级作用域)
}
闭包:变量的“隐形包裹”
闭包是函数与对其词法环境(变量作用域)的引用。通过闭包可实现数据隐私和状态保留:
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2 (count 的值被闭包保留)
对象与类:面向对象的实现
对象的字面量与方法
JS 对象是键值对集合,可通过字面量快速创建:
const person = {
name: "Alice",
greet() {
return `Hello, my name is ${this.name}`;
}
};
console.log(person.greet()); // 输出 "Hello, my name is Alice"
类与继承(ES6)
ES6 引入 class
语法,简化面向对象编程:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
speak() {
return `${this.name} barks`; // 覆写父类方法
}
}
const myDog = new Dog("Buddy");
console.log(myDog.speak()); // 输出 "Buddy barks"
高级语法特性
解构赋值与扩展运算符
ES6 提供简洁语法处理数据结构:
// 解构赋值
const { name, ...rest } = { name: "Alice", age: 30, city: "NY" };
console.log(name); // Alice
console.log(rest); // { age:30, city:"NY" }
// 扩展运算符
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1,2,3,4]
Promise 与异步编程
处理异步操作时,Promise
和 async/await
是核心工具:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("Data loaded!"), 1000);
});
}
async function start() {
try {
const result = await fetchData();
console.log(result); // 1秒后输出 "Data loaded!"
} catch (error) {
console.error(error);
}
}
start();
常见问题与最佳实践
变量提升陷阱
console.log(x); // 输出 undefined(var 被提升但未初始化)
var x = 10;
解决方案:优先使用 let
或 const
避免意外行为。
类型判断与严格比较
console.log(1 == "1"); // true(类型转换)
console.log(1 === "1"); // false(严格比较)
建议:始终使用 ===
和 !==
避免隐式类型转换错误。
结论
掌握 JS 语法不仅是代码书写的起点,更是构建复杂应用的基石。从变量、函数到闭包、类,每个概念都在实际开发中发挥关键作用。本文通过案例和比喻,帮助读者逐步理解语法背后的逻辑。建议读者通过实践项目巩固知识,例如尝试用闭包实现计数器,或用 async/await
编写 API 请求。记住,语法是工具,而解决问题的能力才是核心——保持好奇心,持续探索 JS 的无限可能。