JavaScript之Getters和Setters 平台支持等详细介绍


Posted in Javascript onDecember 07, 2012

来自John Resig早年的文章,大致翻译了一下,以作备忘。
令人高兴的是,我想我终于可以说,“现在,JavaScript的Getters和Setters使用非常广泛,它和每个JavaScript开发者的切身利益息息相关”。靠,我为了说这句话已经等了很久了。
首先,我们先来快速了解什么是Getters和Setters,以及它们为什么很有用。然后,我们来看看现在都有哪些平台支持Gettets和Setters。
Getters和Setters
Getters和Setters使你可以快速获取或设置一个对象的数据。一般来说,一个对象拥有两个方法,分别用于获取和设置某个值,比如:

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

用这种方式写JavaScript的一个明显的好处是:你可以用它来隐藏那些不想让外界直接访问的属性。最终的代码看起来就像下面这样(用闭包保存新创建的Filed对象的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"

我们来模拟上例中的 “隐藏的value属性”,我们的代码就像这样:
function Field(val){ 
var value = val; 
this.__defineGetter__("value", function(){ 
return value; 
}); 
this.__defineSetter__("value", function(val){ 
value = val; 
}); 
}

但是呢,你不喜欢这样写,而倾向在对象的prototype中定义getters和setters(私有变量写在哪并不重要),我们可以用另一种语法。
function Field(val){ 
this.value = val; 
} 
Field.prototype = { 
get value(){ 
return this._value; 
}, 
set value(val){ 
this._value = val; 
} 
};

这种语法看起来很不可思议,但是使用过一段时间之后,接受它也很容易。
接下来是另一个例子,它允许外界获取一个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()方法时,我遇到了各种errors,我彻底晕了。后来我发现问题就出在一个简单的语句上:a[i] = b[i];
如果对象a存在一个setter,名字叫做i,对象b存在一个getter,名字也叫做i,a[i]不是通过别的setter方法赋值的,而是来自b的getter方法。这两个__lookup*__方法使你可以获取原始的函数。(这段翻得有点晦涩,原文如下)

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)
Javascript 相关文章推荐
window.open的页面如何刷新(父页面)上层页面
Dec 28 Javascript
动态显示可输入的字数提示还可以输入的字数
Apr 01 Javascript
javascript日期格式化方法汇总
Oct 04 Javascript
jQuery遍历DOM元素与节点方法详解
Apr 14 Javascript
jQuery判断元素是否显示 是否隐藏的简单实现代码
May 19 Javascript
JS基于面向对象实现的多个倒计时器功能示例
Feb 28 Javascript
webpack构建的详细流程探底
Jan 08 Javascript
Element Input组件分析小结
Oct 11 Javascript
30分钟快速实现小程序语音识别功能
Nov 27 Javascript
vue实现动态按钮功能
May 13 Javascript
详解Angular cli配置过程记录
Nov 07 Javascript
如何用Node.js编写内存效率高的应用程序
Apr 30 Javascript
缓动函数requestAnimationFrame 更好的实现浏览器经动画
Dec 07 #Javascript
javascrpt绑定事件之匿名函数无法解除绑定问题
Dec 06 #Javascript
php图像生成函数之间的区别分析
Dec 06 #Javascript
javascript SpiderMonkey中的函数序列化如何进行
Dec 05 #Javascript
javascript中有趣的反柯里化深入分析
Dec 05 #Javascript
js multiple全选与取消全选实现代码
Dec 04 #Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
Dec 04 #Javascript
You might like
php 获取select下拉列表框的值
2010/05/08 PHP
PDO版本问题 Invalid parameter number: no parameters were bound
2013/01/06 PHP
PHP实现根据浏览器跳转不同语言页面代码
2013/08/02 PHP
zf框架的校验器使用使用示例(自定义校验器和校验器链)
2014/03/13 PHP
微信公众平台天气预报功能开发
2014/07/06 PHP
支付宝接口开发集成支付环境小结
2015/03/17 PHP
Jquery 快速构建可拖曳的购物车DragDrop
2009/11/30 Javascript
js限制textarea每行输入字符串长度的代码
2012/10/31 Javascript
chrome浏览器如何断点调试异步加载的JS
2016/09/05 Javascript
jQuery实现表格与ckeckbox的全选与单选功能
2016/11/24 Javascript
JavaScript实现无穷滚动加载数据
2017/05/06 Javascript
详解React native全局变量的使用(跨组件的通信)
2017/09/07 Javascript
Angular实现的简单定时器功能示例
2017/12/28 Javascript
vue-cli中使用高德地图的方法示例
2019/03/28 Javascript
JavaScript展开操作符(Spread operator)详解
2019/07/20 Javascript
JS实现旋转木马轮播图
2020/01/01 Javascript
[03:48]2014DOTA2 TI专访71DK夺冠不靠小组赛高排名
2014/07/11 DOTA
python检测服务器是否正常
2014/02/16 Python
KMP算法精解及其Python版的代码示例
2016/06/01 Python
Python的时间模块datetime详解
2017/04/17 Python
Python Socket使用实例
2017/12/18 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
移动端html5 meta标签的神奇功效
2016/01/06 HTML / CSS
韩国家庭购物网上商店:Nsmall
2017/05/07 全球购物
trivago美国:全球最大的酒店价格比较网站
2018/01/18 全球购物
RUIFIER官网:英国奢侈高级珠宝品牌
2020/06/12 全球购物
年度考核自我评价
2014/01/25 职场文书
2014年应届大学生毕业自我鉴定
2014/01/31 职场文书
中学生学雷锋活动心得体会
2014/03/10 职场文书
销售主管竞聘书
2014/03/31 职场文书
团支部推优材料
2014/05/21 职场文书
行政处罚决定书
2015/06/24 职场文书
Python机器学习三大件之一numpy
2021/05/10 Python
分享mysql的current_timestamp小坑及解决
2021/11/27 MySQL
Redis 的查询很快的原因解析及Redis 如何保证查询的高效
2022/03/16 Redis