Skip to content

variables.js

文件信息

  • 📄 原文件:01_variables.js
  • 🔤 语言:javascript

JavaScript 变量与数据类型 本文件介绍 JavaScript 中的变量声明和基本数据类型。

完整代码

javascript
/**
 * ============================================================
 *                JavaScript 变量与数据类型
 * ============================================================
 * 本文件介绍 JavaScript 中的变量声明和基本数据类型。
 * ============================================================
 */

console.log("=".repeat(60));
console.log("1. 变量声明");
console.log("=".repeat(60));

// ============================================================
//                    1. 变量声明
// ============================================================

/**
 * 【var、let、const 的区别】
 *
 * var   - 函数作用域,可重复声明,有变量提升
 * let   - 块级作用域,不可重复声明,暂时性死区
 * const - 块级作用域,不可重复声明,必须初始化,不可重新赋值
 *
 * 【最佳实践】优先使用 const,需要重新赋值时使用 let,避免使用 var
 */

// --- var(不推荐)---
var x = 10;
var x = 20;  // 可以重复声明
console.log("var x:", x);

// --- let ---
let y = 10;
// let y = 20;  // 错误:不能重复声明
y = 20;  // 可以重新赋值
console.log("let y:", y);

// --- const ---
const z = 10;
// z = 20;  // 错误:不能重新赋值
console.log("const z:", z);

// 【注意】const 对象的属性可以修改
const person = { name: "Alice" };
person.name = "Bob";  // 可以修改属性
// person = {};  // 错误:不能重新赋值
console.log("const 对象:", person);

// 【变量提升】
console.log("\n--- 变量提升 ---");
console.log("var 提升:", typeof hoistedVar);  // undefined
// console.log(hoistedLet);  // ReferenceError: 暂时性死区
var hoistedVar = "I'm hoisted";

// 【块级作用域】
console.log("\n--- 块级作用域 ---");
{
    let blockLet = "block scoped";
    var blockVar = "function scoped";
}
// console.log(blockLet);  // 错误:blockLet 不可访问
console.log("var 可访问:", blockVar);


console.log("\n" + "=".repeat(60));
console.log("2. 基本数据类型");
console.log("=".repeat(60));

// ============================================================
//                    2. 基本数据类型
// ============================================================

/**
 * JavaScript 有 7 种原始类型 + 1 种引用类型:
 *
 * 原始类型(Primitive):
 * - number    数字(整数和浮点数)
 * - string    字符串
 * - boolean   布尔值
 * - undefined 未定义
 * - null      空值
 * - symbol    符号(ES6+)
 * - bigint    大整数(ES2020+)
 *
 * 引用类型:
 * - object    对象(包括数组、函数等)
 */

// --- Number ---
console.log("\n--- Number ---");
const integer = 42;
const float = 3.14;
const negative = -10;
const infinity = Infinity;
const notANumber = NaN;

console.log("整数:", integer);
console.log("浮点数:", float);
console.log("Infinity:", infinity);
console.log("NaN:", notANumber);
console.log("NaN === NaN:", NaN === NaN);  // false
console.log("Number.isNaN(NaN):", Number.isNaN(NaN));  // true

// 数字方法
console.log("toFixed(2):", (3.14159).toFixed(2));
console.log("parseInt:", parseInt("42px"));
console.log("parseFloat:", parseFloat("3.14abc"));

// --- String ---
console.log("\n--- String ---");
const single = 'single quotes';
const double = "double quotes";
const template = `template literal`;

// 模板字符串
const name = "Alice";
const age = 25;
console.log(`${name} is ${age} years old`);

// 多行字符串
const multiline = `
  Line 1
  Line 2
  Line 3
`;
console.log("多行字符串:", multiline.trim());

// 字符串方法
const str = "Hello, World!";
console.log("length:", str.length);
console.log("toUpperCase:", str.toUpperCase());
console.log("toLowerCase:", str.toLowerCase());
console.log("indexOf:", str.indexOf("World"));
console.log("includes:", str.includes("World"));
console.log("startsWith:", str.startsWith("Hello"));
console.log("slice(0, 5):", str.slice(0, 5));
console.log("split(','):", str.split(","));
console.log("replace:", str.replace("World", "JavaScript"));
console.log("trim:", "  spaces  ".trim());
console.log("padStart:", "5".padStart(3, "0"));
console.log("repeat:", "ab".repeat(3));

// --- Boolean ---
console.log("\n--- Boolean ---");
const truthy = true;
const falsy = false;

// 假值(Falsy)
console.log("假值列表:");
console.log("  false:", Boolean(false));
console.log("  0:", Boolean(0));
console.log("  '':", Boolean(""));
console.log("  null:", Boolean(null));
console.log("  undefined:", Boolean(undefined));
console.log("  NaN:", Boolean(NaN));

// 真值(Truthy)
console.log("真值示例:");
console.log("  []:", Boolean([]));  // true!空数组是真值
console.log("  {}:", Boolean({}));  // true!空对象是真值
console.log("  '0':", Boolean("0"));  // true!非空字符串

// --- undefined 和 null ---
console.log("\n--- undefined 和 null ---");
let undefinedVar;
const nullVar = null;

console.log("undefined:", undefinedVar);
console.log("null:", nullVar);
console.log("typeof undefined:", typeof undefined);
console.log("typeof null:", typeof null);  // "object" - 历史遗留问题
console.log("null == undefined:", null == undefined);  // true
console.log("null === undefined:", null === undefined);  // false

// --- Symbol ---
console.log("\n--- Symbol ---");
const sym1 = Symbol("description");
const sym2 = Symbol("description");
console.log("sym1 === sym2:", sym1 === sym2);  // false,每个 Symbol 都是唯一的

// Symbol 作为对象属性
const obj = {
    [sym1]: "value1",
    normalKey: "value2"
};
console.log("Symbol 属性:", obj[sym1]);
console.log("Object.keys 不包含 Symbol:", Object.keys(obj));

// --- BigInt ---
console.log("\n--- BigInt ---");
const bigInt1 = 9007199254740991n;
const bigInt2 = BigInt("9007199254740992");
console.log("BigInt:", bigInt1);
console.log("BigInt + 1n:", bigInt1 + 1n);
// console.log(bigInt1 + 1);  // 错误:不能混合 BigInt 和 Number


console.log("\n" + "=".repeat(60));
console.log("3. 类型检查与转换");
console.log("=".repeat(60));

// ============================================================
//                    3. 类型检查与转换
// ============================================================

// --- typeof 运算符 ---
console.log("\n--- typeof ---");
console.log("typeof 42:", typeof 42);
console.log("typeof 'hello':", typeof "hello");
console.log("typeof true:", typeof true);
console.log("typeof undefined:", typeof undefined);
console.log("typeof null:", typeof null);  // "object" - 历史遗留
console.log("typeof Symbol():", typeof Symbol());
console.log("typeof {}:", typeof {});
console.log("typeof []:", typeof []);  // "object"
console.log("typeof function(){}:", typeof function(){});

// --- instanceof ---
console.log("\n--- instanceof ---");
console.log("[] instanceof Array:", [] instanceof Array);
console.log("{} instanceof Object:", {} instanceof Object);
console.log("new Date() instanceof Date:", new Date() instanceof Date);

// --- 类型转换 ---
console.log("\n--- 显式类型转换 ---");

// 转换为字符串
console.log("String(123):", String(123));
console.log("(123).toString():", (123).toString());
console.log("'' + 123:", "" + 123);

// 转换为数字
console.log("Number('123'):", Number("123"));
console.log("parseInt('123'):", parseInt("123"));
console.log("parseFloat('3.14'):", parseFloat("3.14"));
console.log("+'123':", +"123");

// 转换为布尔值
console.log("Boolean(1):", Boolean(1));
console.log("!!1:", !!1);

// --- 隐式类型转换 ---
console.log("\n--- 隐式类型转换 ---");
console.log("'5' + 3:", "5" + 3);  // "53"
console.log("'5' - 3:", "5" - 3);  // 2
console.log("'5' * '2':", "5" * "2");  // 10
console.log("true + true:", true + true);  // 2
console.log("[] + []:", [] + []);  // ""
console.log("[] + {}:", [] + {});  // "[object Object]"


console.log("\n" + "=".repeat(60));
console.log("4. 相等性比较");
console.log("=".repeat(60));

// ============================================================
//                    4. 相等性比较
// ============================================================

/**
 * == (宽松相等):会进行类型转换
 * === (严格相等):不进行类型转换,推荐使用
 * Object.is():与 === 类似,但处理 NaN 和 ±0 不同
 */

console.log("\n--- == vs === ---");
console.log("5 == '5':", 5 == "5");    // true
console.log("5 === '5':", 5 === "5");  // false

console.log("null == undefined:", null == undefined);    // true
console.log("null === undefined:", null === undefined);  // false

console.log("0 == false:", 0 == false);    // true
console.log("0 === false:", 0 === false);  // false

// --- Object.is ---
console.log("\n--- Object.is ---");
console.log("Object.is(NaN, NaN):", Object.is(NaN, NaN));  // true
console.log("Object.is(0, -0):", Object.is(0, -0));  // false
console.log("0 === -0:", 0 === -0);  // true


console.log("\n" + "=".repeat(60));
console.log("5. 解构赋值");
console.log("=".repeat(60));

// ============================================================
//                    5. 解构赋值
// ============================================================

// --- 数组解构 ---
console.log("\n--- 数组解构 ---");
const [a, b, c] = [1, 2, 3];
console.log("a, b, c:", a, b, c);

// 跳过元素
const [first, , third] = [1, 2, 3];
console.log("first, third:", first, third);

// 剩余元素
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log("head:", head);
console.log("tail:", tail);

// 默认值
const [val1, val2 = 10] = [1];
console.log("val1, val2:", val1, val2);

// 交换变量
let swap1 = 1, swap2 = 2;
[swap1, swap2] = [swap2, swap1];
console.log("交换后:", swap1, swap2);

// --- 对象解构 ---
console.log("\n--- 对象解构 ---");
const { name: userName, age: userAge } = { name: "Alice", age: 25 };
console.log("userName, userAge:", userName, userAge);

// 同名简写
const { name: n, age: a2 } = { name: "Bob", age: 30 };
console.log("n, a2:", n, a2);

// 嵌套解构
const user = {
    id: 1,
    profile: {
        email: "[email protected]",
        avatar: "avatar.png"
    }
};
const { profile: { email } } = user;
console.log("email:", email);

// 默认值
const { missing = "default" } = {};
console.log("missing:", missing);

// 函数参数解构
function greet({ name, greeting = "Hello" }) {
    console.log(`${greeting}, ${name}!`);
}
greet({ name: "Alice" });


console.log("\n" + "=".repeat(60));
console.log("6. 展开运算符");
console.log("=".repeat(60));

// ============================================================
//                    6. 展开运算符 (Spread Operator)
// ============================================================

// --- 数组展开 ---
console.log("\n--- 数组展开 ---");
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2];
console.log("合并数组:", merged);

// 复制数组
const copy = [...arr1];
console.log("复制数组:", copy);

// 函数调用
console.log("Math.max:", Math.max(...arr1));

// --- 对象展开 ---
console.log("\n--- 对象展开 ---");
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = { ...obj1, ...obj2 };
console.log("合并对象:", mergedObj);

// 覆盖属性
const updated = { ...obj1, b: 10, e: 5 };
console.log("覆盖属性:", updated);

// 浅拷贝
const original = { nested: { value: 1 } };
const shallowCopy = { ...original };
shallowCopy.nested.value = 2;
console.log("浅拷贝影响原对象:", original.nested.value);  // 2


console.log("\n【总结】");
console.log(`
- 优先使用 const,需要重新赋值时使用 let
- 使用 === 而不是 ==
- 了解假值:false, 0, '', null, undefined, NaN
- 善用解构赋值和展开运算符
- typeof 检查基本类型,instanceof 检查对象类型
`);

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布