0

0

JavaScript 中对象 setter 递归调用导致栈溢出的原理与解决方案

花韻仙語

花韻仙語

发布时间:2026-02-12 15:01:23

|

141人浏览过

|

来源于php中文网

原创

JavaScript 中对象 setter 递归调用导致栈溢出的原理与解决方案

本文详解 `maximum call stack size exceeded` 在对象 setter 中的成因:当 setter 内部直接赋值给同名属性时,会无限触发自身,引发递归调用直至溢出;核心解法是使用私有命名约定(如 `_age`)分离内部存储与访问接口。

在 JavaScript 中,对象的 set 访问器(setter)本质上是一个函数,每当对目标属性执行赋值操作(如 obj.age = 20)时,引擎会自动调用对应的 setter 函数。关键陷阱在于:若该 setter 函数体内再次对同一属性名进行赋值(如 this.age = value),就会形成隐式递归调用——因为 this.age = value 并非简单写入数据,而是再次触发 set age(),如此循环往复,最终耗尽调用栈空间,抛出 RangeError: Maximum call stack size exceeded。

以原始代码为例:

set age(value) {
  if (value < 18) {
    console.log(`${value} - You are underage :(`);
  } else {
    this.age = value; // ❌ 危险!此处再次调用 set age()
  }
}

user.age = 20 → 触发 set age(20) → 执行 this.age = 20 → 再次触发 set age(20) → …… 无限递归。

✅ 正确做法是引入一个内部存储属性(通常以 _ 开头作为命名约定,表示“仅供内部使用”),将数据保存到该属性中,避免触发 setter 自身:

传声港
传声港

AI驱动的综合媒体服务平台,提供 “媒体发稿 + 自媒体宣发 + 效果监测” 一站式服务

下载

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

let user = {
  name: "Fra",
  surname: "Emme",

  set age(value) {
    if (value < 18) {
      console.log(`${value} - You are underage :(`);
    } else {
      this._age = value; // ✅ 写入私有字段,不触发 setter
    }
  },

  get age() {
    return this._age; // ✅ 提供配套 getter,保持属性可读
  },

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set place(value) {
    if (value === "" || value === null || value.length <= 2) {
      console.log("Invalid place");
      return;
    }
    this._place = value; // ✅ 同理,避免 this.place = value
  },

  get place() {
    return this._place;
  }
};

user.age = 20;
user.place = "Rovereto";
console.log(user); // { name: "Fra", surname: "Emme", _age: 20, _place: "Rovereto" }

⚠️ 注意事项:

  • getter 必须配套实现:仅定义 setter 而无 getter 会导致属性不可读(访问 user.age 返回 undefined),且可能干扰 for...in 或 Object.keys() 等遍历行为。
  • 命名约定非强制但强烈推荐:_age 是社区广泛接受的私有字段标识,虽不能真正阻止外部访问,但清晰表达了设计意图;ES2022 引入的 #privateField 语法(需 #age)可提供真正私有性,但目前对象字面量中尚不支持私有字段(仅类中可用)。
  • 避免逻辑耦合副作用:setter 中应专注数据校验与存储,避免嵌入复杂业务逻辑或异步操作,否则易引发难以调试的副作用。

总结:setter 的本质是拦截赋值行为,而非普通变量赋值。任何在 setter 内对同名属性的写操作都会重新进入该 setter,这是 JavaScript 访问器机制的固有特性。理解并规避这一“自调用陷阱”,是掌握现代 JavaScript 对象封装能力的关键一步。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1393

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

319

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2209

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

36

2026.01.19

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

410

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

587

2023.08.10

undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

5564

2023.07.31

网页undefined是什么意思
网页undefined是什么意思

网页undefined是指页面出现了未知错误的意思,提示undefined一般是在开发网站的时候定义不正确或是转换不正确,或是找不到定义才会提示undefined未定义这个错误。想了解更多的相关内容,可以阅读本专题下面的文章。

3179

2024.08.14

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

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

189

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号