You need to enable JavaScript to run this app. JavaScript中setter的作用是什么?两种写法的等效性与适用场景区分
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中setter的作用是什么?两种写法的等效性与适用场景区分

JavaScript Setter 的核心作用

Setter 是 JavaScript 对象的访问器属性(accessor property)的组成部分,核心作用是拦截对指定属性的赋值操作,将原本直接修改对象属性的行为,关联到开发者自定义的函数逻辑上。
和普通对象属性不同,setter可以让开发者完全掌控属性赋值的执行路径,自由实现数据校验、赋值日志记录、关联状态联动更新、视图触发更新等自定义逻辑,避免外部代码无约束地修改对象内部状态。结合给出的示例代码来看,对象language里定义的set current(name),并不是在对象上创建一个叫current的可存储的普通属性,而是当外部代码对language.current执行赋值操作时,自动把传入的赋值参数传给这个函数执行:示例里函数内部把传入的语言名称推送到log数组里,整个过程不会真的给current属性写入实际的存储值。

两段示例代码的执行效果对比

在当前给出的极简逻辑下,两段代码最终在控制台输出的language.log内容完全一致,都是 ['EN', 'FA']。
但二者的实现逻辑有本质区别,存在大量场景会导致输出结果不同:

  • 第一段代码的行为是通过属性赋值的拦截逻辑完成log更新,所有对current的赋值都会被setter函数接管,执行push操作的前提是触发了current属性的赋值动作。
  • 第二段代码的行为是直接操作log数组的push方法,不存在任何拦截校验逻辑,只要执行到push语句,值就会被追加到数组中。

常见的结果差异场景包括:

  • setter加入参数校验逻辑时
    如果给setter增加合法性判断,不是所有传入值都会被推到log里,比如修改setter逻辑为只接受两位长度的字符串作为语言代码:
    set current(name) {
      if (typeof name === 'string' && name.length === 2) {
        this.log.push(name);
      }
    }
    
    此时如果执行language.current = 123,赋值操作会被校验拦截,不会往log里添加内容;但第二段代码直接执行language.log.push(123)时,会无差别把数字值追加到log中,二者输出完全不同。
  • setter加入去重、状态联动等业务逻辑时
    如果setter里增加了去重判断,避免重复添加相同的语言值:
    set current(name) {
      if (!this.log.includes(name)) {
        this.log.push(name);
      }
    }
    
    此时连续两次执行language.current = 'EN',第一段代码的log里只会保留一个'EN';但第二段代码连续执行两次push('EN')的话,log数组里会出现两个重复的'EN'。
  • setter存在异步处理逻辑时
    如果setter内没有同步执行push,而是把值放入异步队列延迟处理:
    set current(name) {
      setTimeout(() => this.log.push(name), 0)
    }
    
    此时赋值完成后立刻同步读取language.log,第一段代码拿到的是空数组;但第二段代码的push是同步执行的,立刻读取就能拿到已添加的内容。
  • 对象属性配置变动时
    如果后续代码通过Object.defineProperty把current属性从访问器属性改成普通可读写的存储属性,第一段代码对current的赋值就不会再触发原有的push逻辑,log不会被更新;但第二段直接操作log数组的逻辑不会受这类属性修改的影响,始终会把值追加到数组里。

内容的提问来源于stack exchange,提问作者Chandan Shetti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.30 10:27:03