0

0

JavaScript 中函数内重赋值自身名称的原理与闭包效应

碧海醫心

碧海醫心

发布时间:2026-02-12 13:28:33

|

885人浏览过

|

来源于php中文网

原创

JavaScript 中函数内重赋值自身名称的原理与闭包效应

本文解析为何在函数体内对函数名重新赋值会改变其行为:`fun1()` 通过首次调用时重定义全局函数引用并捕获闭包中的数组,实现“单例数组复用”;而 `fun2()` 每次调用都新建数组,返回独立副本。二者本质差异在于作用域绑定、执行时机与内存生命周期。

在 JavaScript 中,函数名在非严格模式下(尤其作为函数声明时)会作为可写属性被注入到当前词法环境的外层作用域(通常是全局或模块顶层)中。这一特性常被用于实现“惰性初始化”(lazy initialization)或“函数自替换”(function self-overwriting)模式——fun1 正是典型应用。

我们来逐步拆解 fun1 的执行逻辑:

function fun1() {
  const arr = ["a", "b", "c", "d", "e"];
  fun1 = function () {  // ⚠️ 关键:直接赋值给标识符 fun1
    return arr;
  };
  return fun1(); // 此处调用的是刚重定义的新函数
}
  • 首次调用 fun1()

    1. 创建新数组 arr(地址记为 0x100);
    2. 执行 fun1 = function() { return arr; } —— 此操作修改了外层作用域中 fun1 变量的引用,使其指向一个新函数;
    3. 该新函数形成了闭包,持久持有对 arr(0x100)的引用
    4. return fun1() 实际调用这个新函数,返回 arr 的引用(而非拷贝)。
  • 后续调用 fun1()
    原始函数体不再执行,直接进入闭包函数,始终返回同一个 arr 实例(0x100)。因此对返回值的修改(如 .pop())会真实反映在后续调用结果中。

相比之下,fun2 是纯粹的“无状态工厂函数”:

一键职达
一键职达

AI全自动批量代投简历软件,自动浏览招聘网站从海量职位中用AI匹配职位并完成投递的全自动操作,真正实现'一键职达'的便捷体验。

下载

立即学习Java免费学习笔记(深入)”;

function fun2() {
  const arr = ["a", "b", "c", "d", "e"]; // 每次调用都新建数组(新内存地址)
  return arr; // 返回新数组的引用
}

每次调用 fun2() 都会创建一个全新数组实例,彼此内存隔离,互不影响。

✅ 验证关键点:检查函数身份与数组引用

可通过以下代码直观验证两者的差异:

console.log(fun1.toString() !== fun2.toString()); // true —— fun1 已被重定义
console.log(fun1() === fun1()); // true —— 同一数组引用
console.log(fun2() === fun2()); // false —— 不同数组实例

⚠️ 注意事项与陷阱

  • 仅在非严格模式/函数声明下生效:若 fun1 被定义为 const fun1 = function() {...} 或在严格模式中,对 fun1 的赋值将抛出 TypeError(不可写绑定)。
  • 非线程安全:在并发调用场景下,首次竞争可能导致未定义行为(尽管实际中极少发生)。
  • 调试难度高:函数行为在运行时动态变更,违背“纯函数”直觉,增加维护成本。
  • 替代方案更推荐:现代代码应优先使用模块级私有变量 + 闭包,语义更清晰:
// 推荐:显式封装,意图明确
const fun1 = (() => {
  const arr = ["a", "b", "c", "d", "e"];
  return () => arr;
})();

总结

fun1 的“魔法”并非来自语法黑科技,而是 JavaScript 函数声明提升(hoisting)与变量可写性共同作用的结果:它利用首次调用完成一次性初始化 + 闭包固化 + 函数重绑定三重效果,实现了轻量级单例数组缓存;而 fun2 则遵循常规函数语义,保证每次调用的独立性。理解这一机制,有助于识别遗留代码中的隐式状态管理,并在必要时安全复用该模式(建议辅以注释说明其惰性初始化意图)。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

542

2023.09.20

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

653

2023.08.10

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

140

2025.07.29

function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

491

2023.08.04

js函数function用法
js函数function用法

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。本专题提供js函数function用法的相关文章内容,大家可以免费阅读。

166

2023.10.07

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

189

2026.02.11

Yandex网页版官方入口使用指南_国际版与俄罗斯版访问方法解析
Yandex网页版官方入口使用指南_国际版与俄罗斯版访问方法解析

本专题全面整理了Yandex搜索引擎的官方入口信息,涵盖国际版与俄罗斯版官网访问方式、网页版直达入口及免登录使用说明,帮助用户快速、安全地进入Yandex官网,高效使用其搜索与相关服务。

590

2026.02.11

虫虫漫画网页版入口与免费阅读指南_正版漫画全集在线查看方法
虫虫漫画网页版入口与免费阅读指南_正版漫画全集在线查看方法

本专题系统整理了虫虫漫画官网及网页版最新入口,涵盖免登录观看、正版漫画全集在线阅读方式,并汇总稳定可用的访问渠道,帮助用户快速找到虫虫漫画官方页面,轻松在线阅读各类热门漫画内容。

90

2026.02.11

Docker容器化部署与DevOps实践
Docker容器化部署与DevOps实践

本专题面向后端与运维开发者,系统讲解 Docker 容器化技术在实际项目中的应用。内容涵盖 Docker 镜像构建、容器运行机制、Docker Compose 多服务编排,以及在 DevOps 流程中的持续集成与持续部署实践。通过真实场景演示,帮助开发者实现应用的快速部署、环境一致性与运维自动化。

7

2026.02.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 5万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号