JavaScript 核心知识学习笔记:给Java开发者的实战指南

开篇:从Java到JavaScript的转变

作为一名Java开发者开始学习JavaScript时,我发现最大的挑战不是语法本身,而是思维方式的转变。Java是强类型、面向对象的语言,而JavaScript是弱类型、原型继承的脚本语言。这篇文章记录了我学习JS核心概念时的心得,特别会指出与Java的关键差异。

一、String(字符串):比Java更灵活的文本处理

与Java的核心差异

在Java中,String是不可变对象,我们习惯用StringBuilder来拼接。但JavaScript的字符串处理要灵活得多。

javascript 复制代码
// JavaScript的字符串声明
        let str1 = "Hello";
        let str2 = 'World';
        let str3 = `Hello ${str2}`;
        console.log(str3);    

// Java中需要:
// String str3 = String.format("Hello %s", str2);

字符串拼接的演进

javascript 复制代码
let name = "张三";
let age = 25;

// 方式1:传统拼接(类似Java)
let msg1 = "姓名:" + name + ",年龄:" + age;

// 方式2:模板字符串(推荐)
let msg2 = `姓名:${name},年龄:${age}`;

// 甚至可以在${}中执行表达式
let msg3 = `明年年龄:${age + 1}`;

这比Java的StringBuilder或String.format()直观很多,我现在基本只用模板字符串。

常用方法对比

javascript 复制代码
let text = "JavaScript";

// Java: text.length()  ->  JavaScript: text.length(注意没有括号)
console.log(text.length); // 10

// 大小写转换(与Java类似)
text.toUpperCase();  // "JAVASCRIPT"
text.toLowerCase();  // "javascript"

// 查找子串
text.includes("Script");     // true(Java 需要用 contains())
text.indexOf("Script");      // 4(与Java相同)
text.startsWith("Java");     // true
text.endsWith("Script");     // true

// 截取(注意参数与Java的substring略有不同)
text.slice(0, 4);           // "Java"(推荐用这个)
text.substring(0, 4);       // "Java"(与Java行为类似)

// 替换
text.replace("Java", "Type"); // "TypeScript"(只替换第一个)
text.replaceAll("a", "A");   // "JAvaScript"(替换所有)

// 分割成数组
text.split("");  // ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]

实战案例:输入验证

javascript 复制代码
function validateUsername(username) {
    // 去除首尾空格(类似Java的trim())
    username = username.trim();
    
    // 长度检查
    if (username.length < 3 || username.length > 20) {
        return { valid: false, message: "用户名长度必须在3-20之间" };
    }
    
    // 格式检查(只允许字母、数字、下划线)
    let pattern = /^[a-zA-Z0-9_]+$/;
    if (!pattern.test(username)) {
        return { valid: false, message: "用户名只能包含字母、数字和下划线" };
    }
    
    return { valid: true, message: "验证通过" };
}

console.log(validateUsername("user_123"));  // { valid: true, ... }
console.log(validateUsername("ab"));        // { valid: false, ... }

二、Array(数组):比Java数组强大百倍

关键差异认知

这是我从Java转JS时最大的惊喜:JavaScript的数组是动态的、功能丰富的

javascript 复制代码
// Java: int[] arr = new int[5];  固定长度
// JavaScript: 数组是动态的,可以随时增删

let arr = [];  // 空数组
arr.push(1);   // 添加元素
arr.push(2);
arr.push(3);
console.log(arr.length); // 3

// 可以存储不同类型(与Java泛型不同)
let mixed = [1, "text", true, { name: "obj" }]; // 完全合法

基础操作

javascript 复制代码
let numbers = [1, 2, 3, 4, 5];

// 添加/删除元素
numbers.push(6);        // 末尾添加:[1,2,3,4,5,6]
numbers.pop();          // 末尾删除:[1,2,3,4,5]
numbers.unshift(0);     // 开头添加:[0,1,2,3,4,5]
numbers.shift();        // 开头删除:[1,2,3,4,5]

// 查找元素
numbers.indexOf(3);     // 2(返回索引,类似Java的Arrays.asList().indexOf())
numbers.includes(3);    // true

// 截取(类似Java的Arrays.copyOfRange())
let sliced = numbers.slice(1, 3); // [2, 3]

函数式编程方法(重点!)

这是JavaScript相比Java数组最强大的地方。虽然Java 8也引入了Stream API,但JS的数组方法更简洁直观。

javascript 复制代码
let products = [
    { id: 1, name: "笔记本", price: 5000, inStock: true },
    { id: 2, name: "鼠标", price: 100, inStock: true },
    { id: 3, name: "键盘", price: 300, inStock: false },
    { id: 4, name: "显示器", price: 2000, inStock: true }
];

// filter:筛选(类似Java的Stream.filter())
let inStockProducts = products.filter(p => p.inStock);
// Java: products.stream().filter(p -> p.isInStock()).collect(Collectors.toList());

// map:转换(类似Java的Stream.map())
let names = products.map(p => p.name);
// Java: products.stream().map(Product::getName).collect(Collectors.toList());

// find:查找第一个匹配项(类似Java的Stream.findFirst())
let expensiveProduct = products.find(p => p.price > 1000);

// reduce:聚合(类似Java的Stream.reduce())
let totalPrice = products.reduce((sum, p) => sum + p.price, 0);
// Java: products.stream().mapToInt(Product::getPrice).sum();

// some:至少有一个满足条件(类似Java的Stream.anyMatch())
let hasExpensive = products.some(p => p.price > 1000); // true

// every:全部满足条件(类似Java的Stream.allMatch())
let allInStock = products.every(p => p.inStock); // false

// 链式调用
let result = products
    .filter(p => p.inStock)
    .map(p => ({ name: p.name, price: p.price }))
    .sort((a, b) => a.price - b.price);
console.log("In-stock products:", inStockProducts);
console.log("Product names:", names);

实战案例:数据处理

javascript 复制代码
// 场景:处理从API获取的订单数据
let orders = [
    { orderId: "001", userId: 1, amount: 299, status: "completed" },
    { orderId: "002", userId: 2, amount: 599, status: "pending" },
    { orderId: "003", userId: 1, amount: 199, status: "completed" },
    { orderId: "004", userId: 3, amount: 899, status: "completed" }
];

// 统计某用户的已完成订单总额
function getTotalAmount(userId) {
    return orders
        .filter(order => order.userId === userId && order.status === "completed")
        .reduce((total, order) => total + order.amount, 0);
}

console.log(getTotalAmount(1)); // 498

// 按金额分组
function groupByAmount() {
    return {
        low: orders.filter(o => o.amount < 300),
        medium: orders.filter(o => o.amount >= 300 && o.amount < 600),
        high: orders.filter(o => o.amount >= 600)
    };
}

三、Object(对象):理解原型而非类

思维转变

Java中我们用class定义对象,JavaScript虽然ES6也引入了class关键字,但本质是原型继承。对象字面量的使用非常频繁。

javascript 复制代码
// JavaScript对象字面量(最常用)
let user = {
    id: 1,
    username: "admin",
    email: "admin@example.com",
    
    // 方法
    getInfo: function() {
        return `${this.username} (${this.email})`;
    }
};

// 等价的Java代码需要先定义类:
// public class User {
//     private int id;
//     private String username;
//     private String email;
//     public String getInfo() { ... }
// }
// User user = new User();

对象操作

javascript 复制代码
let config = {
    apiUrl: "https://api.example.com",
    timeout: 5000,
    retries: 3
};

// 访问属性
console.log(config.apiUrl);        // 点号访问
console.log(config["timeout"]);    // 括号访问(动态属性名时很有用)

// 动态属性名
let propName = "retries";
console.log(config[propName]);     // 3

// 添加属性
config.debug = true;

// 删除属性(Java中不常见的操作)
delete config.debug;

// 检查属性是否存在
if ("timeout" in config) {
    console.log("timeout配置存在");
}

// 获取所有属性名(类似Java的反射)
let keys = Object.keys(config);     // ["apiUrl", "timeout", "retries"]
let values = Object.values(config); // 对应的值数组
let entries = Object.entries(config); // [["apiUrl", "..."], ...]

对象解构(ES6特性)

这是JavaScript特有的语法糖,能大幅简化代码:

javascript 复制代码
let user = {
    id: 1,
    username: "zhangsan",
    email: "zhangsan@example.com",
    role: "admin"
};

// 传统方式
let username = user.username;
let email = user.email;

// 解构赋值
let { username, email } = user;

// 函数参数解构(特别实用)
function sendEmail({ email, username }) {
    console.log(`发送邮件给 ${username}: ${email}`);
}

sendEmail(user);  // 直接传入对象,自动提取需要的属性

四、JSON:前后端数据交换的桥梁

与Java对比

在Java中,我们用Jackson或Gson来序列化/反序列化对象。JavaScript原生就支持JSON操作,这是它的一大优势。

javascript 复制代码
// Java需要:
// ObjectMapper mapper = new ObjectMapper();
// String json = mapper.writeValueAsString(object);
// Object obj = mapper.readValue(json, Object.class);

// JavaScript只需要:
let jsonString = JSON.stringify(object);
let object = JSON.parse(jsonString);

JSON.stringify:将 JavaScript对象转换为 JSON字符串,便于网络传输或本地存储。

JSON.parse:将 JSON字符串解析为 JavaScript对象,实现数据的读取和使用。

基础操作

javascript 复制代码
let userData = {
    userId: 1001,
    username: "lisi",
    roles: ["user", "editor"],
    metadata: {
        lastLogin: "2025-10-22",
        loginCount: 15
    }
};

// 对象转JSON字符串
let jsonStr = JSON.stringify(userData);
console.log(jsonStr);
// '{"userId":1001,"username":"lisi","roles":["user","editor"],"metadata":{...}}'

// 格式化输出(带缩进)
let prettyJson = JSON.stringify(userData, null, 2);
console.log(prettyJson);

// JSON字符串转对象
let parsed = JSON.parse(jsonStr);
console.log(parsed.username); // "lisi"

实战场景:API数据处理

javascript 复制代码
// 场景:处理REST API响应
function fetchUserData(userId) {
    // 模拟API响应的JSON字符串
    let response = `{
        "code": 200,
        "message": "success",
        "data": {
            "user": {
                "id": ${userId},
                "name": "张三",
                "email": "zhangsan@example.com"
            },
            "permissions": ["read", "write"]
        }
    }`;
    
    // 解析JSON
    let result = JSON.parse(response);
    
    if (result.code === 200) {
        return result.data;
    } else {
        throw new Error(result.message);
    }
}

// 使用
try {
    let userData = fetchUserData(1001);
    console.log(`用户名:${userData.user.name}`);
    console.log(`权限:${userData.permissions.join(", ")}`);
} catch (error) {
    console.error("获取用户数据失败:", error.message);
}

数据转换与验证

javascript 复制代码
// 场景:表单数据提交
function submitForm(formData) {
    // 构建请求体
    let requestBody = {
        username: formData.username.trim(),
        email: formData.email.toLowerCase(),
        age: parseInt(formData.age),
        timestamp: Date.now()
    };
    
    // 验证
    if (!requestBody.username || requestBody.username.length < 3) {
        throw new Error("用户名至少3个字符");
    }
    
    // 转换为JSON
    let jsonData = JSON.stringify(requestBody);
    
    // 模拟发送请求
    console.log("发送数据:", jsonData);
    return jsonData;
}

// 测试
try {
    submitForm({
        username: "test_user",
        email: "TEST@EXAMPLE.COM",
        age: "25"
    });
} catch (error) {
    console.error(error.message);
}

五、DOM:网页操作的核心API

与Java Swing/JavaFX的对比

如果你写过Java桌面应用,DOM操作类似于Swing的组件操作,但更直接、更动态。

基础选择器

javascript 复制代码
// 获取元素的几种方式
let element1 = document.getElementById("myId");              // 通过ID
let elements1 = document.getElementsByClassName("myClass");  // 通过类名(返回集合)
let elements2 = document.getElementsByTagName("div");        // 通过标签名
let element2 = document.querySelector(".myClass");           // CSS选择器(推荐)
let elements3 = document.querySelectorAll(".myClass");       // 所有匹配元素

我的建议:优先使用querySelectorquerySelectorAll,它们更灵活,支持所有CSS选择器,也是。当前最为常用的。

实战案例1:动态表格生成

假设有这样的HTML结构:

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>用户列表</title>
    <style>
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #4CAF50; color: white; }
    </style>
</head>
<body>
    <div id="app">
        <h2>用户管理</h2>
        <table id="userTable">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>姓名</th>
                    <th>邮箱</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="tableBody"></tbody>
        </table>
    </div>
    
    <script src="app.js"></script>
</body>
</html>

JavaScript代码(app.js):

javascript 复制代码
// 模拟从API获取的数据
let users = [
    { id: 1, name: "张三", email: "zhangsan@example.com" },
    { id: 2, name: "李四", email: "lisi@example.com" },
    { id: 3, name: "王五", email: "wangwu@example.com" }
];

// 渲染表格
function renderTable() {
    let tbody = document.getElementById("tableBody");
    tbody.innerHTML = "";  // 清空现有内容
    
    users.forEach(user => {
        let row = document.createElement("tr");
        
        row.innerHTML = `
            <td>${user.id}</td>
            <td>${user.name}</td>
            <td>${user.email}</td>
            <td>
                <button onclick="editUser(${user.id})">编辑</button>
                <button onclick="deleteUser(${user.id})">删除</button>
            </td>
        `;
        
        tbody.appendChild(row);
    });
}

// 编辑用户
function editUser(id) {
    let user = users.find(u => u.id === id);
    if (user) {
        let newName = prompt("输入新姓名:", user.name);
        if (newName) {
            user.name = newName;
            renderTable();  // 重新渲染
        }
    }
}

// 删除用户
function deleteUser(id) {
    if (confirm("确定要删除吗?")) {
        users = users.filter(u => u.id !== id);
        renderTable();
    }
}

// 页面加载时渲染表格
document.addEventListener("DOMContentLoaded", function() {
    renderTable();
});

以上HTML JS代码执行结果:

实战案例2:表单处理与验证

HTML结构:

html 复制代码
<form id="loginForm">
    <div>
        <label for="username">用户名:</label>
        <input type="text" id="username" name="username">
        <span id="usernameError" style="color: red;"></span>
    </div>
    <div>
        <label for="password">密码:</label>
        <input type="password" id="password" name="password">
        <span id="passwordError" style="color: red;"></span>
    </div>
    <button type="submit">登录</button>
</form>
<div id="result"></div>

JavaScript代码:

javascript 复制代码
let form = document.getElementById("loginForm");

form.addEventListener("submit", function(event) {
    event.preventDefault();  // 阻止表单默认提交行为
    
    // 清空之前的错误信息
    document.getElementById("usernameError").textContent = "";
    document.getElementById("passwordError").textContent = "";
    
    // 获取表单数据
    let username = document.getElementById("username").value.trim();
    let password = document.getElementById("password").value;
    
    // 验证
    let isValid = true;
    
    if (username.length < 3) {
        document.getElementById("usernameError").textContent = "用户名至少3个字符";
        isValid = false;
    }
    
    if (password.length < 6) {
        document.getElementById("passwordError").textContent = "密码至少6个字符";
        isValid = false;
    }
    
    if (isValid) {
        // 提交数据
        submitLogin(username, password);
    }
});

function submitLogin(username, password) {
    // 模拟API请求
    let loginData = {
        username: username,
        password: password,
        timestamp: Date.now()
    };
    
    console.log("提交登录:", JSON.stringify(loginData));
    
    // 显示结果
    document.getElementById("result").innerHTML = 
        `<p style="color: green;">登录成功!欢迎 ${username}</p>`;
}

六、BOM:浏览器对象模型

核心概念

BOM提供了与浏览器交互的接口,这是Java开发中不会接触到的领域。主要包括:

  • window:全局对象

  • navigator:浏览器信息

  • location:URL操作

  • history:浏览历史

  • screen:屏幕信息

window对象

javascript 复制代码
// 弹窗(开发调试时常用)
alert("提示信息");
let confirmed = confirm("确定要删除吗?");  // 返回boolean
let input = prompt("请输入姓名:", "默认值");

// 定时器(类似Java的Timer)定时器任务我常用SpringTask
setTimeout(function() {
    console.log("3秒后执行");
}, 3000);

let intervalId = setInterval(function() {
    console.log("每2秒执行一次");
}, 2000);

// 清除定时器
clearInterval(intervalId);

// 页面尺寸
console.log(window.innerWidth);   // 视口宽度
console.log(window.innerHeight);  // 视口高度

location对象

javascript 复制代码
// URL操作
console.log(location.href);      // 完整URL
console.log(location.hostname);  // 主机名
console.log(location.pathname);  // 路径
console.log(location.search);    // 查询字符串

// 跳转
location.href = "https://example.com";
location.reload();  // 刷新页面

// 解析URL参数
function getUrlParams() {
    let params = {};
    let queryString = location.search.substring(1);
    let pairs = queryString.split("&");
    
    pairs.forEach(pair => {
        let [key, value] = pair.split("=");
        params[key] = decodeURIComponent(value);
    });
    
    return params;
}

// 使用URLSearchParams(现代方式)
let params = new URLSearchParams(location.search);
console.log(params.get("id"));  // 获取参数值

localStorage(本地存储)

javascript 复制代码
// 存储数据(类似Java的Properties文件)
localStorage.setItem("username", "zhangsan");
localStorage.setItem("theme", "dark");

// 存储对象需要序列化
let user = { id: 1, name: "张三" };
localStorage.setItem("user", JSON.stringify(user));

// 读取数据
let username = localStorage.getItem("username");
let userStr = localStorage.getItem("user");
let userObj = JSON.parse(userStr);

// 删除数据
localStorage.removeItem("username");
localStorage.clear();  // 清空所有

实战案例:会话管理

javascript 复制代码
// 用户会话管理类
class SessionManager {
    constructor() {
        this.TOKEN_KEY = "auth_token";
        this.USER_KEY = "user_info";
    }
    
    // 保存登录信息
    saveSession(token, userInfo) {
        localStorage.setItem(this.TOKEN_KEY, token);
        localStorage.setItem(this.USER_KEY, JSON.stringify(userInfo));
    }
    
    // 获取token
    getToken() {
        return localStorage.getItem(this.TOKEN_KEY);
    }
    
    // 获取用户信息
    getUserInfo() {
        let userStr = localStorage.getItem(this.USER_KEY);
        return userStr ? JSON.parse(userStr) : null;
    }
    
    // 检查是否登录
    isLoggedIn() {
        return this.getToken() !== null;
    }
    
    // 登出
    logout() {
        localStorage.removeItem(this.TOKEN_KEY);
        localStorage.removeItem(this.USER_KEY);
        location.href = "/login.html";
    }
}

// 使用
let session = new SessionManager();

// 登录后保存会话
session.saveSession("abc123token", {
    id: 1,
    username: "zhangsan",
    role: "admin"
});

// 页面加载时检查登录状态
if (!session.isLoggedIn()) {
    location.href = "/login.html";
} else {
    let user = session.getUserInfo();
    console.log(`欢迎回来,${user.username}!`);
}

总结:Java开发者学习JS的建议

从Java转到JavaScript这段时间,最大的收获是理解了这两种语言在设计理念上的根本差异。Java追求严谨和可控,而JavaScript更注重灵活和实用。刚开始我总想用Java的思维去理解JS,比如纠结于没有强类型、对象不是基于类的等等,但慢慢发现这正是JavaScript的优势所在。

相关推荐
狡猾大先生5 小时前
ESP32S3-Cam实践(LedStrip、RC舵机控制)
笔记
heisd_15 小时前
ROS 学习
学习
鸽子一号5 小时前
c#笔记之事件
笔记
喜欢吃燃面6 小时前
算法中的链表结构
开发语言·c++·学习·算法
Lovely Ruby6 小时前
七日 Go 的自学笔记 (一)
开发语言·笔记·golang
crary,记忆6 小时前
Angular如何让整个项目的所有页面能够整体缩小一定的比例?
javascript·ecmascript·angular.js
冷崖6 小时前
const 与 constexpr
c++·学习
wenjie学长6 小时前
[UE学习笔记]—划时代意义的两大功能—lumen和Nanite
笔记·学习·ue·三维数字化
好奇龙猫6 小时前
日语学习-日语知识点小记-构建基础-JLPT-N3阶段-二阶段(6):文法運用
学习