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 相关文章推荐
img的onload的另类用法
Jan 10 Javascript
javascript 动态参数判空操作
Dec 22 Javascript
jQuery 源码分析笔记(5) jQuery.support
Jun 19 Javascript
js innerHTML 改变div内容的方法
Aug 03 Javascript
原生JS实现仿淘宝网左侧商品分类菜单效果代码
Sep 10 Javascript
封装好的javascript前端分页插件pagination
Jan 04 Javascript
Bootstrap实现登录校验表单(带验证码)
Jun 23 Javascript
JavaScript数组去重的多种方法(四种)
Sep 19 Javascript
vue系列之requireJs中引入vue-router的方法
Jul 18 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
Mar 06 jQuery
JavaScript实现横版菜单栏
Mar 17 Javascript
详解JavaScript中的数据类型,以及检测数据类型的方法
Sep 17 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制作静态网站的模板框架
2006/10/09 PHP
array_multisort实现PHP多维数组排序示例讲解
2011/01/04 PHP
php调用MySQL存储过程的方法集合(推荐)
2013/07/03 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
URL编码转换,escape() encodeURI() encodeURIComponent()
2006/12/27 Javascript
用javascript getComputedStyle获取和设置style的原理
2008/10/10 Javascript
getElementsByTagName vs selectNodes效率 及兼容的selectNodes实现
2010/02/26 Javascript
script标签的 charset 属性使用说明
2010/12/04 Javascript
GRID拖拽行的实例代码
2013/07/18 Javascript
浅析hasOwnProperty方法的应用
2013/11/20 Javascript
jQuery和AngularJS的区别浅析
2015/01/29 Javascript
javascript实现uploadify上传格式以及个数限制
2015/11/23 Javascript
BootStrap的弹出框(Popover)支持鼠标移到弹出层上弹窗层不隐藏的原因及解决办法
2016/04/03 Javascript
Javascript iframe交互并兼容各种浏览器的解决方法
2016/07/12 Javascript
基于JavaScript实现移动端无限加载分页
2017/03/27 Javascript
微信小程序教程系列之视图层的条件渲染(10)
2017/04/19 Javascript
nodejs+websocket实时聊天系统改进版
2017/05/18 NodeJs
JavaScript重复元素处理方法分析【统计个数、计算、去重复等】
2017/12/14 Javascript
微信小程序实现人脸识别
2018/05/25 Javascript
小程序图片剪裁加旋转的示例代码
2018/07/10 Javascript
详解Ubuntu安装angular-cli遇到的坑
2018/09/08 Javascript
解决layer.confirm快速点击会重复触发事件的问题
2019/09/23 Javascript
vue:el-input输入时限制输入的类型操作
2020/08/05 Javascript
[01:17]辉夜杯战队访谈宣传片—EHOME
2015/12/25 DOTA
[01:56]无止竞 再出发——中国军团出征2017年DOTA2国际邀请赛
2017/07/05 DOTA
Python解决走迷宫问题算法示例
2018/07/27 Python
Python-ElasticSearch搜索查询的讲解
2019/02/25 Python
Python+PyQT5的子线程更新UI界面的实例
2019/06/14 Python
django使用xadmin的全局配置详解
2019/11/15 Python
网络教育自我鉴定
2013/11/01 职场文书
专业销售业务员求职信
2013/11/18 职场文书
安全月活动总结
2014/05/05 职场文书
师德师风自查材料
2014/10/14 职场文书
2015军训通讯稿大全
2015/07/18 职场文书
因个人工作失误检讨书
2019/06/21 职场文书
vue3.0 数字翻牌组件的使用方法详解
2022/04/20 Vue.js