当前位置: 首页 > news >正文

JavaScript进阶篇——第二章 高级特性核心

目录

一、闭包

二、变量提升

三、函数提升

四、函数参数

1. 动态参数 (arguments)

2. 剩余参数 (...rest)

五、展开运算符

六、剩余参数 vs 展开运算符


本文摘要:JavaScript核心概念解析,包含闭包、变量/函数提升、函数参数及展开运算符。闭包由内层函数和外层变量组成,用于数据封装;变量提升仅var存在,let/const有块级作用域;函数声明会整体提升。函数参数处理中,剩余参数(...rest)替代arguments更实用。展开运算符(...)用于数组/对象展开、合并等场景。关键区别:let/const无提升,剩余参数是真数组,展开运算符实现浅拷贝。记忆口诀:"闭包封数据,提升要小心,三点神通广"概括核心要点。

一、闭包

核心概念

闭包 = 内层函数 + 外层函数的变量
内层函数可以访问外层函数作用域中的变量

基本结构

function outer() {// 外层函数变量const a = 1;// 内层函数(闭包)function inner() {console.log(a); // 访问外层变量}return inner;
}const closure = outer();
closure(); // 输出 1

简约写法

function counter() {let count = 0;return function() {count++;console.log(`调用次数: ${count}`);};
}const increment = counter();
increment(); // 调用次数: 1
increment(); // 调用次数: 2

实际应用场景

  1. 数据私有化

    function createBankAccount(initial) {let balance = initial; // 私有变量return {deposit: (amount) => balance += amount,withdraw: (amount) => balance -= amount,getBalance: () => balance};
    }const account = createBankAccount(1000);
    account.deposit(500);
    console.log(account.getBalance()); // 1500
    // 无法直接访问 balance

  2. 事件处理封装

    function setupButton(buttonId) {let clickCount = 0;const btn = document.getElementById(buttonId);btn.addEventListener('click', () => {clickCount++;btn.textContent = `点击了 ${clickCount} 次`;});
    }setupButton('myBtn');

⚠️ 注意事项

  1. 闭包会导致外部函数变量无法被GC回收

  2. 过度使用可能导致内存泄漏

  3. 在循环中创建闭包需谨慎


二、变量提升

核心机制

var 声明的变量会被提升到当前作用域顶部
只提升声明,不提升赋值

代码示例

console.log(name); // undefined(不会报错)
var name = '小明';
console.log(name); // '小明'// 实际执行顺序:
// var name;          // 声明提升
// console.log(name); // undefined
// name = '小明';     // 赋值
// console.log(name); // '小明'

不同声明方式对比

声明方式变量提升块作用域重复声明初始值
varundefined
let未初始化
const必须赋值

❗ 最佳实践

  1. 始终使用 let 和 const

  2. 避免使用 var

  3. 声明放在作用域顶部


三、函数提升

函数声明 vs 函数表达式

类型提升调用时机示例
函数声明声明前后均可调用function foo() {}
函数表达式赋值后调用const bar = function() {}

代码示例

// 函数声明(可提升)
sayHello(); // ✅ 正常执行
function sayHello() {console.log('Hello!');
}// 函数表达式(不提升)
try {sayHi(); // ❌ 报错
} catch(e) {console.error(e); // TypeError: sayHi is not a function
}
const sayHi = function() {console.log('Hi!');
}

⚠️ 注意事项

  1. 函数声明整体提升(包括函数体)

  2. 函数表达式仅提升变量声明(类似var)

  3. 避免在块内使用函数声明(行为不一致)


四、函数参数

1. 动态参数 (arguments)

函数内部伪数组,包含所有传入的实参

function sum() {let total = 0;for(let i = 0; i < arguments.length; i++) {total += arguments[i];}return total;
}console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20));  // 30
特点:
  • 伪数组(有length,无数组方法)

  • 箭头函数不可用

  • 不推荐使用(被剩余参数替代)

2. 剩余参数 (...rest)

将多余实参收集到真数组

function config(baseURL, ...other) {console.log('基础URL:', baseURL);console.log('其他参数:', other);
}config('https://api.com', 'GET', 'json', true);
/* 输出:
基础URL: https://api.com
其他参数: ['GET', 'json', true]
*/
优势:
  • 真数组(可使用所有数组方法)

  • 清晰区分必需参数和可选参数

  • 箭头函数可用


五、展开运算符

核心功能

将数组展开为逗号分隔的元素序列

应用场景

// 1. 求数组最大/最小值
const scores = [95, 89, 72, 100];
console.log(Math.max(...scores)); // 100
console.log(Math.min(...scores)); // 72// 2. 合并数组
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2, 5];
console.log(combined); // [1, 2, 3, 4, 5]// 3. 复制数组
const original = [10, 20];
const copy = [...original]; // 浅拷贝// 4. 函数参数传递
const points = [5, 10, 15];
function plot(x, y, z) {console.log(`坐标: (${x},${y},${z})`);
}
plot(...points); // 坐标: (5,10,15)// 5. 对象展开(ES2018+)
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a:1, b:2, c:3 }

⚠️ 注意事项

  1. 展开运算符实现的是浅拷贝

  2. 对象展开是ES2018新增特性

  3. 字符串也可展开:console.log(...'hello') // h e l l o


六、剩余参数 vs 展开运算符

对比解析

特性剩余参数展开运算符
语法位置函数参数列表数组/对象字面量
主要功能收集多余参数为数组展开数组/对象为元素序列
符号... 在形参前... 在数组/对象前
结果类型数组逗号分隔序列
典型场景函数定义中处理不定数量参数函数调用、数组合并、对象合并

代码示例

// 剩余参数(收集)
function collect(a, b, ...rest) {console.log(rest);
}
collect(1, 2, 3, 4); // [3, 4]// 展开运算符(展开)
const nums = [3, 4];
collect(1, 2, ...nums); // [3, 4] 等价于 collect(1,2,3,4)

✅ 高级特性核心要点总结

📝 高频面试题速答

  1. Q:什么是闭包?有什么作用?

    A:闭包是内层函数+外层变量,用于数据封装和私有化

  2. Q:let/const 和 var 的主要区别?

    A:let/const有块作用域且不提升,var有函数作用域且会提升

  3. Q:剩余参数和 arguments 的区别?

    A:剩余参数是真数组,arguments是伪数组

  4. Q:展开运算符的主要用途?

    A:展开数组/对象,用于函数传参、数组合并、对象合并等

  5. Q:函数声明和函数表达式的区别?

    A:函数声明会提升,函数表达式不会提升


🧠 记忆口诀

"闭包封数据,提升要小心,三点神通广"

  • 闭包:封装数据实现私有化

  • 提升:var和函数声明会提升

  • 三点... 既是剩余参数也是展开运算符

http://www.dtcms.com/a/279736.html

相关文章:

  • vue笔记4 vue3核心语法和pinia基础使用
  • 【leetcode】326. 3的幂
  • VSCode中使用容器及容器编排docker-compose
  • L1与L2正则化详解:原理、API使用与实践指南
  • FastAPI + gRPC 全栈实践:Windows 开发到 Ubuntu 部署全指南
  • JVM监控及诊断工具-命令行篇
  • ubuntu 22.04 anaconda comfyui安装
  • 8.数据库索引
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘collections’问题
  • WIFI MTU含义 ,协商修改的过程案例分析
  • ansys2021R Fluent 的UDF配置问题
  • 开疆智能EtherCAT转CANopen网关连接磁导航传感器配置案例
  • 《美术教育研究》是什么级别的期刊?是正规期刊吗?能评职称吗?
  • Python项目中Protocol Buffers的应用示例
  • MySQL Innodb Cluster介绍
  • 零基础 “入坑” Java--- 十一、多态
  • Spring Boot + Vue2 实现腾讯云 COS 文件上传:从零搭建分片上传系统
  • 并发编程核心概念详解:进程、线程与协程的本质与差异
  • 解锁HTTP:从理论到实战的奇妙之旅
  • Windows系统使用docker部署项目(有网与离线)
  • LeetCode--45.跳跃游戏 II
  • 破局与重构:文心大模型开源的产业变革密码
  • 北京饮马河科技公司 Java 实习面经
  • vscode 打开项目时候,有部分外部依赖包找不到定义或者声明,但是能使用cmake正常编译并且运行
  • C#——数据与变量
  • 软件构件组装三层次体系:定制、集成与扩展的深度解析
  • Product Hunt 每日产品热榜 | 2025-07-14
  • 【氮化镓】非辐射复合载流子诱导的瞬态缺陷机制
  • 实现dify关于python安装包功能的实现
  • java进阶(三):单例、工厂、模版方法与代理模式详解