JavaScript Getters和Setters详解:语法、平台支持与注意事项

作者:函数茶馆

时间:2026-10-27

浏览:476

本文详细介绍JavaScript中Getters和Setters的使用方法与平台支持情况。通过示例展示如何定义访问器属性、隐藏内部状态,并对比传统方法与__defineGetter__及新语法的区别。文章还涵盖了Firefox、Safari等浏览器的兼容性列表,以及对象继承中处理Getters和Setters的注意事项。

文章目录

JavaScript Getters和Setters概述

本文基于John Resig早期的文章进行大致翻译,旨在作为技术备忘。


令人欣慰的是,如今JavaScript中的Getters和Setters已得到广泛应用,这与每位JavaScript开发者的日常工作息息相关。为了表达这一观点,作者等待已久。


首先,我们将快速了解Getters和Setters的概念及其重要性,随后探讨当前支持该特性的主要平台。


Getters和Setters

Getters和Setters的基本用法

Getters和Setters允许你快速获取或设置对象的数据。通常,一个对象包含两个方法,分别用于获取和设置某个值,例如:


代码如下:

 
{ 
getValue: function(){
return this._value;
}, 
setValue: function(val){
this._value = val;
} 
} 

使用这种方式编写JavaScript的一个显著优势是:它可以隐藏那些不希望被外部直接访问的属性。最终的代码结构如下(利用闭包保存新创建的Field对象的value):


代码如下:

 
function Field(val){
var value = val;
this.getValue = function(){
return value;
}; 
this.setValue = function(val){
value = val;
}; 
} 

因此,我们可以这样使用:


代码如下:

 
var field = new Field("test");
field.value
// => undefined
field.setValue("test2")
field.getValue()
// => "test2"

使用__defineGetter__和__defineSetter__

为了模拟上述示例中“隐藏的value属性”,我们的代码可以写成这样:


代码如下:

 
function Field(val){
var value = val;
this.__defineGetter__("value", function(){
return value;
}); 
this.__defineSetter__("value", function(val){
value = val;
}); 
} 

Prototype中定义Getters和Setters

如果你不喜欢这种写法,而倾向于在对象的prototype中定义getters和setters(私有变量的位置并不重要),可以使用另一种语法。


代码如下:

 
function Field(val){
this.value = val;
} 
Field.prototype = {
get value(){
return this._value;
}, 
set value(val){
this._value = val;
} 
}; 

这种语法初看可能令人惊讶,但使用一段时间后,接受它变得很容易。


Getters和Setters的高级应用与继承

接下来是另一个示例,它允许外界获取一个username数组,但无法获取原始的、隐藏的user对象。


代码如下:

 
function Site(users){
this.__defineGetter__("users", function(){
// JS 1.6 Array map()
return users.map(function(user){
return user.name;
}); 
}; 
} 

作为补充,我编写了一个方法,用于实现对象的继承,并考虑到了getters和setters的情况。


代码如下:

 
// Helper method for extending one object with another
function extend(a,b) {
for ( var i in b ) {
var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
if ( g || s ) {
if ( g )
a.__defineGetter__(i, g);
if ( s )
a.__defineSetter__(i, s);
} else
a[i] = b[i];
} 
return a;
} 

在我的extend()方法中,你会看到两个新方法:__lookupGetter__和__lookupSetter__。一旦你开始真正使用getters和setters,这些方法将非常有用。


例如,当我第一次编写extend()方法时,遇到了各种错误,让我感到困惑。后来我发现问题出在一个简单的语句上:a[i] = b[i];


如果对象a存在一个名为i的setter,而对象b存在一个名为i的getter,a[i]的值并非通过a的setter方法赋值,而是来自b的getter方法计算出的值。这两个__lookup*__方法允许你访问用于这些方法的原始函数(从而允许你编写有效的extend方法,例如)。



If a setter existed in object a, named i, and a getter existed in object b, named i, a[i]'s value was being set not to the other setter function, but to the computed value from b's getter function. The two __lookup*__ methods allow you to access the original functions used for the methods (thus allowing you to write an effective extend method, for example).


  
记住以下几点:

注意事项与平台支持

一个对象内,每个变量只能有一个getter或setter。(因此value可以有一个getter和一个setter,但value绝没有两个getters)


删除getter或setter的唯一方法是:delete object[name]。delete可以删除一些常见的属性,getters和setters。


如果使用__defineGetter__或__defineSetter__,它会重写之前定义的相同名称的getter或setter,甚至是属性(property)。


平台
支持的浏览器有:

Firefox


Safari 3+


Opera 9.5


(原文没写Chrome,还没出呢)


我用下面的代码测试浏览器:

代码如下:

 
javascript:foo={get test(){ return "foo"; }};alert(foo.test);

另外,以下两种引擎也支持Getters和Setters:


SpiderMonkey


Rhino 1.6R6 (New)

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章