JavaScript 动态生成 Setter 方法:利用 defineSetter 简化类属性封装

作者:代码拾荒

时间:2026-10-21

浏览:530

本文介绍一种在 JavaScript 中自动为类成员生成 setter 方法的技术。通过扩展 Function 原型,利用 __defineSetter__ 的思想实现 defineSetter 和 defineAllSetter,从而避免手动编写大量冗余的 setter 代码,提升代码规范性和开发效率。

文章目录

本文旨在分享代码实现细节,若发现任何问题或疑问,欢迎在评论区留言指正。



JavaScript 类属性封装的挑战

在编写 JavaScript 类时,例如:


 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


为了增强代码的可读性,并清晰区分公共(public)与私有(private)变量,我通常习惯通过定义 set... 方法来赋值给类的成员变量。这些 set 方法自然属于公共接口。此外,这种做法也有助于使代码结构更加规范。



然而,这样做会带来一个显著问题:如果不对输入值进行有效性验证(或仅进行简单验证),代码量将大幅增加。试想如果一个类包含 20 个成员属性,就需要手动编写 20 个对应的 set... 方法,这显然过于冗余。因此,我们需要一种机制来解决这一问题。



仿写 __defineSetter 的实现思路

回顾 Mozilla 浏览器中提供的 __defineSetter__ 和 __defineGetter__ 方法,它们允许开发者为 DOM 对象动态添加成员,极大地方便了开发。受此启发,我们可以尝试在 JavaScript 中仿写一个 __defineSetter 功能。



实现思路如下:


利用 JavaScript 的动态特性,为对象动态添加方法或属性。


这样,类中原本需要手动添加的 set... 方法就不再必要了。


同时,对于非字母区间(非 [a-z] 区间)的属性,也不再需要添加对应的 set... 方法。



核心代码实现与原型扩展

以下是具体的实现代码:


var _defineSetter = function (self, p, hdle) {    //如果属性为空或js中认为是false的值,则返回    if (!p || !self || "function"!=typeof self)     return null;    //强制转型,并将self置为该Function(即class)的引用,当然你也可以添加类中属性set方法,而非prototype属性的set方法    p = String(p); self = self.prototype;    //如果该成员不是一个方法(function),则添加set..方法    if ("function"!=typeof self[p]) {      var n = (function _n (n) {        n = String(n); for (var i=0; i<n.length; i++) {          var letter = n.substring(0,1).toUpperCase();          n = n.substr(1);          if (/[a-z]/i.test(letter))          return 'set'+letter+n;        }; return null;      }) (p); //得到set...这个成员,下面为该成员动态添加方法,如果没有自定义方法,则添加function(v){this[p]=v}的方法;      if (n && hdle && "function"==typeof hdle)        self[n] = new Function("v", "this." +p+ "=" +hdle+ ".apply(this,[v]);");      else        self[n] = new Function("v", "this." +p+ "=v;");      return self[n];    }    return self;  }; 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]


上述代码基本实现了 _defineSetter 的功能。但如果我们需要为每个属性单独调用 defineSetter,仍然显得繁琐。既然原型已经实现,我们可以将其动态绑定到 Function 对象上,只需一行代码即可解决所有 set... 方法的生成问题。


Function.prototype.defineAllSetter = function (hdle) {



for (var i in this.prototype)


_defineSetter.apply(this, [this,i,hdle]);



return this;



};

接下来,我们再绑定一个 defineSetter 给 Function 对象。



Function.prototype.defineSetter = function (p, hdle) {



return _defineSetter.apply(this,


[this].concat(Array.prototype.slice.call(arguments,0)));



};

至此,基本功能已实现。大家可以尝试运行测试。


 

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

本例的 DEMO 及完整代码地址:


http://www.never-online.net/code/js/defineSetter/



当然,我们可以在其中加入验证逻辑,具体代码此处不再赘述,因为核心功能已经实现。有兴趣的读者可以尝试自行扩展。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章