# JavaScript 核心概念

# 🌐 JavaScript 是什么?

  • 定义:运行在客户端的 解释型 脚本语言
  • 核心作用
    网页特效 - 响应用户行为实现动态交互
    表单验证 - 对输入数据进行合法性校验
    数据交互 - 前后端数据通信与渲染
    🚀 服务端开发 - Node.js 运行时环境

📌 特性:单线程 / 事件驱动 / 非阻塞 I/O


# 🧱 JavaScript 组成体系

# 1. ECMAScript (语言基础)

<pre class="mermaid">graph TD
ES [ECMAScript] --> 语法
ES --> 类型系统
ES --> 关键字
ES --> 内置对象 </pre>

# 2. Web APIs (浏览器扩展)

模块功能描述典型 API 示例
DOM文档对象模型 <br> 操作页面元素querySelector() <br> addEventListener()
BOM浏览器对象模型 <br> 控制浏览器行为alert() <br> localStorage
// 组成结构示意代码
const JavaScript = {
  ECMAScript: { 
    version: 'ES2022',
    features: ['箭头函数', 'Promise', '解构赋值']
  },
  WebAPIs: {
    DOM: ['节点操作', '事件处理'],
    BOM: ['窗口控制', '历史记录']
  }
};

# 🔑 核心知识总结

# 1. ECMAScript 三要素

<pre class="mermaid">pie
title 语言基础组成
"变量与类型系统" : 35
"流程控制" : 25
"函数与作用域" : 40</pre>

# 2. Web APIs 能力矩阵

分类关键能力典型应用场景
DOM节点操作 / 事件监听 / 样式控制动态表单 / 页面交互
BOM窗口控制 / 存储 / 导航本地存储 / 页面跳转

# 3. 执行机制要点

// 事件循环示例
console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('End');
// 输出顺序:Start → End → Promise → Timeout

# 4. 关键概念对比

概念特点示例
var/let/const作用域 / 提升 / 重复声明let 块级作用域
== vs ===类型转换差异0 == false → true
同步 / 异步执行队列优先级Promise > setTimeout

# 5. DOM 操作三步骤

  1. 获取元素
    querySelector() / getElementById()
  2. 绑定事件
    addEventListener('click', handler)
  3. 更新状态
    修改 className/style/innerHTML 等属性

📌 来自当前案例的最佳实践:
在按钮切换样式中,通过 className 属性更新类名实现状态切换,注意这会覆盖原有类名

💡 扩展阅读:MDN Web Docs - JavaScript 指南

# JavaScript 书写位置

# 📍 代码组织方式

# 1. 内部脚本(Internal)

<!DOCTYPE html>
<html>
<body>
  <!-- 推荐位置 -->
  <script>
    // 1. 使用独立 script 标签
    // 2. 建议放在 body 闭合前(确保 DOM 加载)
    console.log('内部脚本执行');
  </script>
</body>
</html>

特点

  • 🟢 快速原型开发
  • 🔴 难以维护 / 复用
  • ⚠️ 多个脚本按顺序执行

# 2. 外部脚本(External)

<head>
  <!-- 最佳实践:添加 defer 属性 -->
  <script src="app.js" defer></script>
</head>

模块化方案
<pre class="mermaid">graph LR
HTML --> Script [script 标签]
Script --> JS [JS 文件]
JS --> Function [功能模块]
Function --> Export [导出]
HTML --> Import [导入使用]</pre>

加载策略执行时机适用场景
deferDOM 解析后顺序执行常规依赖
async异步加载立即执行独立第三方库

# 3. 内联脚本(Inline) ⚠️慎用

<button onclick="handleClick()">点击</button>

替代方案

// 推荐的事件绑定方式
document.querySelector('button').addEventListener('click', handleClick);

三种方式对比

类型可维护性缓存适用场景
内部★☆☆☆☆快速测试 / 小型项目
外部★★★★★中大型项目
内联★☆☆☆☆特殊演示场景

📌 最佳实践

  1. 生产环境推荐使用 外部脚本+defer
  2. 避免混用多种加载方式
  3. 使用 ES Module 实现现代模块化

# JavaScript 输入输出语法

# 💻 输出方式对比

<pre class="mermaid">flowchart TD
A [输出方式] --> B [页面输出]
A --> C [控制台输出]
A --> D [弹窗输出]
B --> B1{document.write}
C --> C1{console.log}
D --> D1{alert}</pre>

# 1. 页面内容输出

<script>
  document.write('<h3>动态内容</h3>'); // 会解析 HTML 标签
  document.write('<p style="color:blue">异步内容</p>');
</script>

特点

  • 🟢 快速插入内容
  • 🔴 覆盖已有文档流(在已加载的页面中使用会清空内容)
  • ⚠️ 仅适合初始化阶段使用

# 2. 控制台输出

console.debug('调试信息');    // 蓝色提示
console.warn('警告信息');     // 黄色警告 
console.error('错误信息');    // 红色错误

调试技巧
<pre class="mermaid">pie
title 控制台使用频率
"console.log" : 65
"断点调试" : 25
"其他方法" : 10</pre>

# 3. 弹窗输出

alert('操作成功!'); 
// 模态对话框,阻塞后续代码执行

# ⌨️ 输入方式

const userName = prompt('请输入用户名:'); 
// 返回值类型:String|null

输入处理流程
<pre class="mermaid">sequenceDiagram
用户 ->> 浏览器:点击确认
浏览器 ->>JS: 返回输入值
用户 ->> 浏览器:点击取消
浏览器 ->>JS: 返回 null</pre>


# ⚡ 执行特性

# 代码执行优先级

  1. 同步代码 > 弹窗交互 > DOM 渲染
  2. 示例现象:
<script>
  alert('阻断渲染'); // 先执行
  document.write('内容'); // 后执行
</script>

# 最佳实践建议

场景推荐方式原因
调试信息console.debug无副作用 / 分类明确
用户交互自定义模态框样式可控 / 体验更好
页面初始化document.write便捷高效
生产环境日志console.info便于日志收集

⚠️ 注意事项

  1. alert () 会阻塞事件循环,现代前端框架中已较少使用
  2. prompt () 返回值需做类型检查:
    const input = prompt() || 'default'

# JavaScript 变量使用指南

# 📦 变量声明三剑客

<pre class="mermaid">flowchart TD
A [声明方式] --> B ["var(旧标准)"]
A --> C ["let(块级作用域)"]
A --> D ["const(常量)"]</pre>

# 声明方式对比

特性varletconst
作用域函数级块级块级
重复声明✅允许❌禁止❌禁止
暂时性死区❌不存在✅存在✅存在
变量提升✅声明提升
初始值要求❌不需要❌不需要✅必须

# 🔧 使用场景示例

# 1. 基础使用

// 变量声明周期
let count = 0;          // 可变的量
const MAX_SIZE = 100;   // 不变的常量
var oldVar = '弃用';    // 旧写法(不推荐)
// 变量更新
count = count + 1;      // ✅ 合法
// MAX_SIZE = 200;      // ❌ TypeError

# 2. 作用域差异

function demo() {
  if(true) {
    var a = 1;
    let b = 2;
    const c = 3;
  }
  console.log(a); // 1 ✅
  // console.log(b); // ❌ ReferenceError
  // console.log(c); // ❌ ReferenceError
}

# 3. 变量提升现象

console.log(x); //undefined(变量提升)
var x = 5;
// console.log(y); // ❌ ReferenceError
let y = 10;

# 🚩 最佳实践

# 命名规范

<pre class="mermaid">pie
title 命名风格
"camelCase" : 65
"CONSTANT_CASE" : 25
"其他" : 10</pre>

  1. 基础规则

    • 字母 / 下划线 /$ 开头
    • 区分大小写
    • 避免保留字
  2. 语义化命名

    // Bad
    let a = 3600; 
    // Good
    const MAX_TIMEOUT_MS = 3600;
    let userLoginToken;

# 使用建议

  1. 优先使用 const ,其次 let ,不用 var
  2. 使用 'use strict' 开启严格模式
  3. 复杂对象使用 Object.freeze() 创建深层常量
    const config = Object.freeze({ api: 'https://api.example.com' });

# ❗ 常见问题

# 1. 未声明变量

function demo() {
  count = 10; // 自动成为全局变量(严格模式下报错)
}

# 2. 动态类型陷阱

let price = 100;     // number
price = '$100';      //string(合法但易出错)

# 3. 闭包引用

for(var i=0; i<3; i++) {
  setTimeout(() => console.log(i), 100); // 输出 3 次 3
}
// 解决方案:改用 let 声明 i

💡 调试技巧:使用 typeof 检查类型:
console.log(typeof count); // "number"

# 变量存储原理与命名规范

# 🧠 变量本质与内存管理

// 示例:变量与内存的关系
let a = 10;    // 内存分配 4 字节存储数字 10
a = 'text';    // 重新分配内存存储字符串
let b = a;     // 引用同一内存地址

# 核心概念

  1. 内存单元

    • 每个变量占用特定内存空间
    • 大小由数据类型决定(Number: 8 字节,Boolean: 1 字节...)
  2. 变量生命周期

    1. 声明阶段 → 分配内存
    2. 赋值阶段 → 写入数据
    3. 使用阶段 → 读取数据
    4. 销毁阶段 → 内存释放(垃圾回收)
  3. 特殊现象

// 地址引用示例
let arr1 = [1,2];
let arr2 = arr1;
arr2.push(3);
console.log(arr1); // [1,2,3] (共享内存地址)

# 📝 命名规则(强制遵守)

# 语法规则

  • ✅ 允许字符:字母 / 数字 / 下划线 (_)/ 美元符 ($)
  • ✅ 开头禁止:数字开头无效( let 2name; // ❌
  • ✅ 大小写敏感: nameName
  • ✅ 保留字禁用: let class = 'test'; // ❌

# 作用域规则

function test() {
  var localVar = '局部';  // 函数作用域
  let blockVar = '块级';  // 块级作用域
}
// console.log(localVar); // ❌ ReferenceError

# 🎨 命名规范(推荐遵守)

# 基础原则

规范类型正确示例错误示例
语义化命名userAgea
避免单个字母indexi (循环变量除外)
常量全大写MAX_SIZEmaxSize
布尔值前缀isValid / hasTokencheck

# 进阶建议

  1. 项目一致性

    • 选择一种命名风格(camelCase/PascalCase)并统一
  2. 避免缩写

    • calculatePrice 而非 calcPrc
  3. 类型暗示

// 数组复数形式
const users = ['Alice', 'Bob']; 
// 函数动词开头
function validateForm() {}
// Promise 对象加 Async 后缀
let loginAsync = fetch('/api');

# ⚠️ 注意事项

  1. 严格模式要求
'use strict';
age = 25; // ❌ ReferenceError(必须先声明)
  1. 全局污染风险
function setGlobal() {
  globalVar = '危险!'; // 自动成为 window 属性
}
  1. 命名冲突检测
// ESLint 规则示例
/* eslint no-redeclare: "error" */
let x = 1;
let x = 2; // ❌ 触发警告

# 数组操作基础

# 🧩 数组声明与初始化

// 方式 1:字面量声明(推荐)
let fruits = ['苹果', '香蕉']; 
// 方式 2:构造函数声明
let numbers = new Array(1, 2, 3);
// 混合类型数组
let mixed = [1, '文本', true, {name: '对象'}];

# 声明方式对比

方式可读性特殊场景注意点
字面量★★★★★常规初始化首选方式
构造函数★★☆☆☆创建空数组 / 指定长度数组new Array(3) 创建长度为 3 的空槽数组

# 🔍 数据访问与操作

// 基础访问
let firstFruit = fruits[0]; // ' 苹果'
fruits[2] = '橘子';         // 自动扩容
// 长度属性
let count = fruits.length;  // 3(动态更新)
// 越界访问示例
console.log(fruits[5]);     //undefined(不会报错)

# 索引规则

索引类型示例返回值安全性
有效正索引arr[0]元素值✅安全
负索引arr[-1]undefined⚠️需转换
超范围索引arr[100]undefined⚠️注意
非整数索引arr[1.5]undefined⚠️无效

# 🌟 数组特性

# 1. 动态类型支持

// 多类型元素示例
let smartArray = [
  100,                         // Number
  '字符串',                    // String
  { type: '对象' },            // Object
  [1, 2],                      // Array
  function() { return '函数' } // Function
];

# 2. 长度动态变化

let arr = [];
arr[5] = '跳跃赋值';
console.log(arr.length); // 6(自动填充空位)
console.log(arr);        // [空 ×5, "跳跃赋值"]

# 3. 引用类型特性

let a = [1,2];
let b = a;
b.push(3);
console.log(a); // [1,2,3](共享内存地址)

# 🚩 最佳实践

  1. 初始化建议

    // 创建空数组
    let arr = [];          // ✅ 推荐
    let arr = new Array(); // ⚠️ 少用
    // 创建填充数组
    let nums = Array(5).fill(0); // [0,0,0,0,0]
  2. 安全访问技巧

    // 防止越界
    let last = arr[arr.length - 1] || '默认值';
    // 可选链操作符(ES2020)
    let value = arr?.[10] ?? '不存在';
  3. 类型检测

    console.log(typeof []);              // "object"
    console.log(Array.isArray([1,2]));   //true(推荐检测方式)

⚠️ 常见错误

  1. 混淆索引与长度: arr[arr.length] = ... 导致越界
  2. 误用对象语法: arr{0: '错误'} 应该用方括号
  3. 跳过索引赋值: arr[5] = ... 产生空位

# 常量声明与使用规范

# 🚨 核心特性

const PI = 3.14159;
// PI = 3.14; ❌ TypeError(不可重新赋值)
// 引用类型特殊案例
const USER = { name: 'Alice' };
USER.age = 25; // ✅ 允许修改属性
// USER = {};  ❌ 禁止重新分配内存地址

# 常量 vs 变量

特性constlet
重新赋值
块级作用域
必须初始化
提升行为TDZ(暂时性死区)TDZ(暂时性死区)

# 📝 声明与使用

# 1. 基础语法

// 正确声明
const MAX_SIZE = 100; 
// 错误示例
//const UNINITIALIZED; ❌ 必须初始化

# 2. 引用类型处理

// 数组常量
const COLORS = ['red', 'green'];
COLORS.push('blue'); // ✅ 允许修改内容
// COLORS = ['new']; ❌ 禁止重新赋值
// 对象常量
const CONFIG = { debug: true };
CONFIG.debug = false; // ✅ 修改属性

# 3. 深度冻结技巧

// 实现真正不可变
const IMMUTABLE_OBJ = Object.freeze({ 
  key: 'value' 
});
// IMMUTABLE_OBJ.key = 'new'; ❌ 严格模式报错

# 🚩 最佳实践

# 命名规范

<pre class="mermaid">pie
title 常量命名风格
"全大写 + 下划线" : 75
"PascalCase" : 15
"其他" : 10</pre>

  1. 基础规则

    • 全大写字母 + 下划线分隔( MAX_RETRIES
    • 位于文件顶部集中声明
    • 优先用于配置项和魔法数字
  2. 使用场景

    // 数学常量
    const GOLDEN_RATIO = 1.618; 
    // 环境配置
    const API_ENDPOINT = 'https://api.example.com';
    // 状态码映射
    const HTTP_CODES = Object.freeze({
      OK: 200,
      NOT_FOUND: 404
    });

# ⚠️ 注意事项

# 1. 暂时性死区(TDZ)

// console.log(VAL); ❌ ReferenceError
const VAL = 10;

# 2. 重复声明检查

const TEST = 1;
// const TEST = 2; ❌ SyntaxError

# 3. 浏览器兼容

// IE10 及以下不支持 const
// 使用 Babel 等工具转换

# 4. 引用类型陷阱

const USERS = ['Alice'];
USERS = ['Bob']; // ❌ 错误
USERS[0] = 'Bob'; // ✅ 允许(可能引发意外修改)
// 解决方案:使用 Object.freeze ()
Object.freeze(USERS);
// USERS.push ('Bob'); ❌ 严格模式报错

💡 扩展技巧
使用 Object.defineProperty() 创建不可配置、不可写的属性:

const CONST_DATA = {};
Object.defineProperty(CONST_DATA, 'value', {
  value: 100,
  writable: false,
  configurable: false
});

# JavaScript 数据类型体系

# 📌 两大分类

<pre class="mermaid">graph LR
A [数据类型] --> B [基本类型]
A --> C [引用类型]
B --> 数字
B --> 字符串
B --> 布尔
B --> Undefined
B --> Null
B --> Symbol
C --> 对象
C --> 数组
C --> 函数 </pre>

# 🔢 数字类型(Number)

let price = 99;       // 整数
let score = 89.5;     // 小数
let temp = -40;       // 负数
let result = 0 / 0;   // NaN(Not a Number)

# 特殊值处理

说明示例
Infinity超出数值范围的极大数1.7976931348623157E+10308
-Infinity超出数值范围的极小数-1.7976931348623157E+10308
NaN无效数学操作的结果(具有粘性)0/0 → NaNNaN + 5 → NaN

# 📜 字符串类型(String)

let s1 = "双引号";
let s2 = '单引号';
let s3 = `模板字符串:${s1}${s2}`;

# 模板字符串特性

// 多行文本
const poem = `床前明月光
疑是地上霜`;
// 表达式运算
console.log(`结果:${2 + 3 * 4}`); // "结果:14"

# 转义字符表

符号含义示例
\n换行"第一行\n第二行"
\\反斜杠"路径:C:\\"
\t制表符"姓名\t年龄"

# 🎲 布尔类型(Boolean)

let isLogin = true;    // 已登录
let hasPermission = false; // 无权限

# 逻辑运算规则

操作结果说明
true && 55返回最后一个真值
false || 00返回最后一个假值
!''true空字符串转为 false 取反

# ❓ Undefined 与 Null

let uninitialized;  //undefined(未赋值)
let emptyObj = null; //null(空对象指针)

# 对比差异

特性UndefinedNull
类型检测"undefined""object"
产生场景变量未初始化时显式赋空值时
等同性检测== 返回 true=== 返回 false

# 🔍 类型检测

// 基础用法
typeof 42;          // "number"
typeof 'text';      // "string"
typeof true;        // "boolean"
// 特殊案例
typeof null;        // "object"(历史遗留问题)
typeof function(){};// "function"

# 检测技巧

// 安全检测 null 类型
function isNull(value) {
    return value === null;
}
// 数组类型检测
Array.isArray([1,2]); // true

# 类型转换指南

# 🔄 转换类型对比

<pre class="mermaid">graph TD
A [类型转换] --> B [隐式转换]
A --> C [显式转换]
B --> D [算术运算自动转换]
B --> E [逻辑运算自动转换]
C --> F["Number()"]
C --> G["parseInt()"]
C --> H["parseFloat()"]</pre>


# 🕵️ 隐式转换规则

# 运算符行为差异

运算符转换规则示例结果
+任意操作数为字符串则字符串拼接'3' + 2"32"
- * /全部转换为数字进行运算'8' - '3'5
==类型转换后比较'5' == 5true
===严格不转换比较'5' === 5false

# 实用技巧

// 快速转数字
let price = +'99.5';   // 99.5(正号转换)
let count = '10' * 1;  // 10(算术运算转换)
// 字符串拼接
console.log(2 + '2');  // "22"(数字转字符串)

# 🔧 显式转换方法

# 1. Number()

Number('123')    // 123
Number('12.3元') // NaN(含非数字字符)
Number(true)     // 1
Number('')       // 0(空字符串转为 0)

# 2. parseInt()

parseInt('12px')    // 12(提取整数部分)
parseInt('101', 2)  // 5(二进制转换)
parseInt('3.9')     // 3(舍去小数)

# 3. parseFloat()

parseFloat('3.14.15') // 3.14(提取首个浮点数)
parseFloat('¥99.9')  // NaN(首字符非数字)

# ⚠️ 注意事项

  1. NaN 特性

    typeof NaN;          // "number"
    NaN === NaN;         //false(唯一不等于自身)
    isNaN('字符串');      //true(全局方法)
    Number.isNaN('字符串'); //false(更安全检测)
  2. 空值处理

    Number(null)      // 0
    Number(undefined) // NaN
  3. 布尔转换

    Number(false)    // 0
    Number(true)     // 1

💡 最佳实践:表单输入处理优先使用 parseFloat 组合验证

let input = '¥99.5';
let value = parseFloat(input.replace(/[^\d.]/g, '')) || 0;

# JavaScript 运算符详解

# 💰 赋值运算符

运算符示例等价于说明
=x = 5-基础赋值
+=x += 3x = x + 3加法赋值
-=x -= 2x = x - 2减法赋值
*=x *= 4x = x * 4乘法赋值
/=x /= 2x = x / 2除法赋值
%=x %= 3x = x % 3取余赋值
let count = 10;
count += 5;  // count = 15
count **= 2; // ES7 特性:count = 225(平方运算)

# 🔢 一元运算符

<pre class="mermaid">flowchart TD
A [一元运算符] --> B [算术运算]
A --> C [类型转换]
B --> 自增 / 自减
C --> 正负号转换 </pre>

# 常用操作符

运算符示例说明
++x++后置自增(先返回值再 + 1)
----x前置自减(先 - 1 再返回值)
++'5'转换为数字
--true转换为数字并取反 → -1
!!0逻辑非 → true
let a = 5;
console.log(a++); // 5(输出后 a=6)
console.log(++a); // 7(先 + 1 后输出)

# ⚖️ 比较运算符

运算符说明示例结果
==值相等(隐式转换)'5' == 5true
===严格相等'5' === 5false
!=值不等5 != '5'false
!==严格不等5 !== '5'true
>大于10 > '8'true
<=小于等于5 <= '5'true
// 特殊比较案例
console.log(null == undefined);  // true
console.log(NaN === NaN);        // false

# 🧠 逻辑运算符

<pre class="mermaid">pie
title 逻辑运算符使用频率
"&&" : 45
"||" : 35
"!" : 20</pre>

# 特性说明

运算符说明短路特性示例
&&逻辑与false && alert() 不执行
||逻辑或true || alert() 不执行
!逻辑非!'' → true
// 实用技巧
const username = input || '匿名用户';  // 默认值设置
isValid && submitForm();              // 条件执行

# 🏆 运算符优先级

// 优先级顺序示例
let result = 3 + 4 * 2; // 11(乘法优先)
let flag = 5 > 4 && 2;  //true(比较 > 逻辑)

# 常见优先级排序

  1. () 分组
  2. ++ -- 一元操作
  3. * / %
  4. + -
  5. > >= < <=
  6. == != === !==
  7. &&
  8. ||
  9. = 赋值

💡 最佳实践:复杂表达式使用括号明确优先级

let value = (a + b) * (c - d / 2);

# JavaScript 语句精要

# 表达式 vs 语句

类别特点示例
表达式可被求值,能作为赋值操作右值3 + 4x * y
语句执行操作,通常以分号结尾if(...){...}

📌 关键差异:
let x = (表达式) ✅ 有效
let x = if(...){...} ❌ 无效

# 分支结构

# if 语句标准结构

if (条件1) {
    // 条件 1 为真时执行
} else if (条件2) {
    // 条件 2 为真时执行
} else {
    // 以上条件均不满足时执行
}

实践建议

  • 简单判断可省略花括号(但不推荐)
  • 多条件时优先使用 else if 而非嵌套 if
  • 使用严格比较 === 避免类型转换问题

# 循环与调试

# 循环基础

//for 循环典型结构
for (初始化; 条件; 迭代) {
    // 循环体
}
//while 循环结构
while (条件) {
    // 循环体
}

# 断点调试要点

  1. 浏览器开发者工具 → Sources 面板
  2. 点击行号设置断点
  3. 使用控制按钮逐步执行:
    • Resume:继续执行
    • Step over:跳过函数
    • Step into:进入函数
  4. 观察变量变化和调用栈

调试场景

  • 验证条件判断逻辑
  • 跟踪循环变量变化
  • 检测函数调用顺序

# JavaScript 数组操作全解

# 📦 增:元素添加

方法说明时间复杂度示例
push()末尾追加元素O(1)arr.push('新元素')
unshift()开头插入元素O(n)arr.unshift('首元素')
splice()指定位置插入O(n)arr.splice(2,0,'插入')
扩展运算符合并数组O(n)[...arr1, ...arr2]
let fruits = ['苹果'];
fruits.push('香蕉');      // 末端添加
fruits.unshift('葡萄');   // 开头插入
fruits.splice(1, 0, '芒果'); // 索引 1 处插入

# 🗑️ 删:元素移除

方法说明返回值示例
pop()移除最后一个元素被删元素arr.pop()
shift()移除第一个元素被删元素arr.shift()
splice()删除指定元素被删元素数组arr.splice(0, 2)
filter()过滤创建新数组新数组arr.filter(x => x !== '苹果')
let arr = [1,2,3,4];
arr.pop();          // 删除末尾 → [1,2,3]
arr.splice(1, 2);   // 从索引 1 删 2 个 → [1]

# ✏️ 改:元素修改

方式说明示例
直接索引赋值简单直接修改arr[1] = '新值'
splice()替换指定元素arr.splice(2,1,'替换值')
fill()填充数组arr.fill(0)
let colors = ['red', 'green'];
colors[1] = 'yellow';       // 直接修改 → ['red', 'yellow']
colors.splice(0,1,'blue');  // 替换 → ['blue', 'yellow']

# 🔍 查:元素检索

方法说明返回值示例
indexOf()查找元素索引索引 /-1arr.indexOf('苹果')
includes()判断是否存在booleanarr.includes('香蕉')
find()查找首个符合条件元素元素 /undefinedarr.find(x => x > 2)
some()是否存在符合条件的元素booleanarr.some(x => x % 2 === 0)
const nums = [5, 12, 8];
console.log(nums.indexOf(12));     // 1
console.log(nums.find(x => x > 10)); // 12
console.log(nums.includes(5));     // true

# 🚩 最佳实践

  1. 性能优化
    • 大数据量操作优先使用 push/pop 代替 unshift/shift
    • 使用 filter/map 创建新数组而非直接修改原数组
  2. 现代语法
    // 删除元素新方式(ES2023)
    const newArr = arr.toSpliced(1, 1); // 不改变原数组
  3. 链式操作
    arr.map(x => x*2)
       .filter(x => x > 10)
       .sort((a,b) => a-b);

💡 注意

  • splice 会直接修改原数组, slice 则返回新数组
  • 使用 Object.defineProperty() 可以创建不可变数组
  • 推荐使用 for...of 替代传统 for 循环遍历数组

# 🎯 函数体系

# 📌 函数声明

function getUser() {
  // 业务逻辑
  return data;
}

# 🧩 核心特性

# 🔑 命名规范

✅ 动词前缀 + 小驼峰
✅ 语义化命名,如:
▪ calculateTotal()
▪ validateForm()
▪ fetchUserData()

# 🚀 参数传递

// 基础传参
function createOrder(item, quantity) { 
  /* ... */ 
}
// 默认值保障
const safeSum = (x = 0, y = 0) => x + y;

# 💡 返回值要点

▪ 使用 return 输出结果
▪ 执行后立即终止函数
▪ 无返回值时默认返回 undefined

# ⚠️⚠️ 重要注意

// 同名函数会覆盖
function demo() {}
function demo() {} // ✅ 生效的是此版本
// 参数个数自由
function test(a, b) {
  console.log(arguments); // 接收所有实参
}
test(1,2,3,4); // ✅ a=1, b=2, arguments=[1,2,3,4]

# 🌍 作用域规则

const globalVar = '全局'; // 🌐 全局作用域
function checkScope() {
  const localVar = '局部'; // 🏷️ 局部作用域
  console.log(globalVar); // ✅ 可访问全局
}
console.log(localVar); // ❌ 报错

# 🔍 访问原则

局部变量 → 闭包变量 → 全局变量

# 匿名函数

# ➤ 函数表达式

// 声明后调用
const action = function() { 
  /* 逻辑代码 */
};
action();

# ➤ IIFE 模式

// 写法一:外包裹式
(function() {
  console.log('立即执行');
})();
// 写法二:内执行式
(function() {
  console.log('立即执行');
}());

▲ 核心特性
▸ 两种语法等效
▸ 隔离作用域防止污染
▸ 推荐结尾加分号

# 🔮 布尔类型转换

# 🎯 转换规则

# ▎假值清单(6 种)

转换结果示例
""❌ falseBoolean("")
0 / NaN❌ falseBoolean(0)
null❌ falseBoolean(null)
undefined❌ falseBoolean(undefined)
false❌ false自身

# ▎逻辑运算特性

// && 查找第一个假值
0 && alert()       // 0(短路执行)
'' && 'test'       // ''
NaN && 20          // NaN
// || 查找第一个真值
0 || '默认值'       // ' 默认值'
null || undefined  //undefined(全假返回末值)

# 🔄 隐式类型转换

# 🧠 转换逻辑图

<pre class="mermaid">flowchart TD
A [运算类型] --> B {含字符串?}
B -->| 是 | C [字符串拼接]
B -->| 否 | D [转数字计算]</pre>

# 📜 核心规则

# 1. 算术运算策略

运算符转换规则示例结果
+任意操作数为字符串则拼接'3' + 2"32"
-*/%全部转为数字计算'10' - '5'5

# 2. 特殊值处理

null + 10     // 10(null→0)
undefined + 1 // NaN 
true + false  // 1(true→1, false→0)
[] + {}       // "[object Object]"(对象转字符串)

# ⚠️ 高频陷阱

  1. 空字符串转 0
    '' - 5 → -5 (易导致非预期结果)

  2. 无效数字污染
    'a' * 2 → NaN (后续运算全为 NaN)

  3. 布尔值参与运算
    true + true → 2 (易误判为逻辑运算)

  4. 对象类型转换
    [1] + [2] → "12" (数组转字符串拼接)

# 🎯 对象体系

# 🧩 核心概念

<pre class="mermaid">graph TD
A [对象] --> B [属性]
A --> C [方法]
B --> 数据值
C --> 函数功能 </pre>

本质:无序键值对集合,用于描述实体(如用户 / 商品)

# 🔑 属性操作

# ➤ 增删改查

操作语法注意点示例
对象.属性属性名需合法标识符user.age
对象['属性']支持特殊字符 / 变量访问user['user-name']
对象.属性 = 值直接覆盖原值user.age = 30
delete 对象.属性删除整个属性delete user.address
对象.新属性 = 值自动添加新属性user.gender = 'male'

# ➤ 多词属性处理

const book = {
  'book-title': 'JavaScript指南',  // ✅ 必须使用方括号访问
  '出版日期': '2023-01'          // ✅ 中文属性需用方括号
};
console.log(book['book-title']);  // 正确访问方式
//console.log (book.book-title);  ❌ 语法错误

# 🚀 方法使用

const calculator = {
  // 标准方法定义
  add: function(a, b) { return a + b }, 
  // ES6 简写语法
  multiply(a, b) { return a * b },  
  // 箭头函数方法(注意 this 指向)
  divide: (a, b) => a / b  
};
// 方法调用
calculator.add(2, 3);          // ✅ 常规调用
calculator['multiply'](2, 3);  // ✅ 方括号调用

# 🔄 对象遍历

const phone = {
  brand: 'Xiaomi',
  model: '13 Pro',
  price: 4999
};
for(let key in phone) {
  //key 为字符串类型属性名
  console.log(`属性:${key} → 值:${phone[key]}`); 
}
/* 输出:
属性:brand → 值:Xiaomi
属性:model → 值:13 Pro
属性:price → 值:4999
*/

# 📊 Math 对象

# ▎核心方法速查

方法功能示例结果
Math.PI圆周率常量Math.PI3.14159...
random()[0,1) 随机数Math.random()0.687...
ceil()向上取整Math.ceil(3.2)4
floor()向下取整Math.floor(3.8)3
round()四舍五入Math.round(3.5)4
max()最大值Math.max(2,5,1)5
min()最小值Math.min(2,5,1)1
pow()幂运算Math.pow(2,3)8
abs()绝对值Math.abs(-5)5

# ▎随机数生成公式

/**
 * 生成 N-M 范围内的整数
 * @param {number} N - 最小值
 * @param {number} M - 最大值
 * @returns {number} 随机整数
 */
function getRandomInt(N, M) {
  return Math.floor(Math.random() * (M - N + 1)) + N;
}
// 示例:生成 10-20 的随机数
console.log(getRandomInt(10, 20));

⚠️ 注意事项

  1. for...in 会遍历原型链属性,建议配合 hasOwnProperty 使用
  2. 方法中的箭头函数会改变 this 指向,需谨慎使用
  3. 删除不存在的属性不会报错,返回 true

# 基本数据类型和引用数据类型

简单类型又叫 iben 数据类型或者值类型,复杂类型又叫引用类型。

  • 值类型:简单数据类型 / 基本数据类型,再存储变量的是值本身,因此被叫做值类型
    值类型变量的数据直接存放在变量(栈空间)中
let num1 = 10;
let num2 = num1;
num2 = 20;
console.log(num1); // 10
  • 引用类型:复杂数据类型,在存储变量中存储的仅仅是地址 (引用),因此叫做引用数据类型通过 new 关键字创建的对象。
    引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中。
let obj1 = {
   age: 18;
}
let obj2 = obj1;
obj2.age = 20;
console.log(obj1.age); // 20

# 变量声明

建议:const 优先,尽量用 const

let arr = ['red', 'green'];
arr.push('pink');
console.log(arr);

这里可以把 let 改为 const

  • const 声明的值不能更改,而且 const 声明变量的时候需要在里面进行初始化
  • 但是对于引用数据类型,const 声明的变量,里面存的不是值,不是值,是地址,所以只要不更改地址,那么里面的值是可以更改的。

建议数组和对象使用 const 声明

更新于 阅读次数