ES5 getter setter
最近在学习vuejs,了解到内部实现使用到了es5的Getters和Setters。之前看高程的时候,没有重视这块,今天查看一下文档,了解了他们的作用,再次记录一下,可供以后查看和共享。
定义Getters和Setters:(一共有三种定义方法)
第一种方法: 使用对象字面量创建对象时,可以像下面定义set 和set一样定义,
var obj = {
"a": 1,
get b(){
return this.a + 1;
},
set c(val){
this.a = val + this.a;
}
}; console.log(obj.a); //初始值为1
console.log(obj.b); //
obj.c = 3;
console.log(obj.a); //
第二种方法:通过Object.defineProperty(...)来定义
var d = Date.prototype; Object.defineProperty(d, "year", {
get : function() {
return this.getFullYear();
},
set: function(val) {
this.setFullYear(val);
}
}); var date = new Date();
console.log("*********");
console.log(date.year); //2016
console.log("*********");
第三种方式:
function Filed(val){
var value = val;
this.getValue = function(){
return value;
};
this.setValue = function(val){
value = value = val;
};
} var f = new Filed(20);
console.log("\n**********************");
console.log(f.getValue()); //
f.setValue(30);
console.log(f.getValue()); //
Getters和Setters可以做什么?
目的:给js语言增加覆盖对象单个属性默认的[[Get]]和[[Put]]能力。
实际上,Getters和Setters都是对象上的属性,通过Getters可以调用对象上隐藏的函数来获取值,通过Setters调用隐藏的函数,来为对象属性赋值。
我们知道对象的属性描述符有value、writable、configurable和enumerable。Getters和Setter也可被理解为对象的存取描述符。如果一个对象定义了Getter和Setter,value和writable会被忽略,js只考虑Getter、Setter、configurable和enumerable。
var obj = {
get a(){
return 2;
}
}; Object.defineProperty(obj, "b", {
get: function(){
return this.a * 4;
},
enumerable: true
}); console.log(obj.a); //
console.log(obj.b); //
obj.a = 4;
console.log(obj.a); //
在16行的时候,我们对a进行赋值,但是在17行的时候,依旧输出了2,,这是因为一旦存在存在存取描述符,并且仅设有Getter的话(即便设有Setter),对该属性的赋值会被默认忽略。
var obj = {
get a(){
return 2;
},
set c(val){
this.a = 3;
}
}; Object.defineProperty(obj, "b", {
get: function(){
return this.a * 4;
},
enumerable: true
}); console.log(obj.a); //
console.log(obj.b); //
//obj.a = 4;
obj.c = 4;
console.log(obj.a); //
实际使用代码如下:
var myObject = {
// define a getter for `a`
get a() {
return this._a_;
}, // define a setter for `a`
set a(val) {
this._a_ = val * 2;
}
}; myObject.a = 2; console.log(myObject.a); //
通过Setter和Getter,我们可以动态设置和获取对象属性的值得效果:
var expr = "foo";
var obj = {
a: "aa",
set [expr](val){
this.a = val;
},
get [expr](){
return expr
}
}; obj.foo="bb";
console.log(obj.a); //bb
console.log(obj[expr]); //foo
对于上面的动态设置和获取,不晓得实际用途。
js的[[Get]]和[[Put]]操作
Getter和Setter会对js对象属性的存取产生怎样的影响呢?
[[Get]]操作:
var obj = {
a: 2
};
console.log(obj.a); //
上面代码的背后的机制:
执行的时候,JavaScript 会在对象 obj上执行一次 [[Get]] 操作。JavaScript 内置的 [[Get]] 操作首先根据属性名称检查对象本身是否有该属性,如果这时候找到了,那么就返回它的值;如果没找到,那么会通过该对象的Prototype
链继续向上查找,直到顶层的 Object.prototype
。见下面代码:
var OldObj = function(){};
OldObj.prototype.a = 2;
var obj = new OldObj();
console.log(obj.a); //
[[put]]操作:
var obj = {
a: 2
};
obj.a = 3;
背后的机制:
首先,JavaScript 会触发一个 [[Put]] 操作,它的行为会根据要赋值的属性是否已经直接存在于该对象上而有所不同。如果该属性已经存在了,[[Put]] 操作会执行如下步骤:
- 该属性是否已经定义了
Setter
,如果已经定义了,那么调用它; - 该属性的属性描述符 (Property Descriptor)是否定义了
writable: false
,如果是,那么赋值操作被忽略,如果是strict mode
,那么会抛出TypeError
异常; - 如果没有上述情况,那么给已存在的属性赋值。
如果被赋值的属性不是直接存在于对象上:
- [[Put]] 操作首先会搜索
Prototype
链,如果没有找到foo
,那么就在被赋值的对象上直接创建foo
,并赋值为bar
; - 如果在
Prototype
链上找到了foo
,代码的行为就会变得诡异起来,我们回头再看。在此之前,先来了解一个概念,叫做变量隐藏 (Variable Shadowing)。当一个变量既直接存在于对象本身,又存在于对象的Prototype
链,那我们就可以说对象本身的属性foo
隐藏了存在于Prototype
链的变量foo
。理解了这个概念,我们再来看当变量foo
在Prototype
链上存在的的时候,给foo
赋值可能带来的三种结果: - 如果
foo
在Prototype
链上存在,并且它没有被定义为只读的 (writable: false),那么一个名叫foo
的属性会被直接添加到myObject
,从而造成变量隐藏 (Shadowing)
; - 如果
foo
在Prototype
链上存在,并且被标记为只读的 (writable: false),那么对foo
的赋值操作会被忽略;如果是strict mode
,那么会抛出异常; - 如果
foo
在Prototype
链上存在,并且它具有Setter
,那么Setter
始终会被调用,也就是说没有属性会被直接添加到myObject
上,也不会发生变量隐藏。也许你还记得,当对象属性Setter
存在的时候,给该属性赋值,不会检查writable
。
原文地址:js Getters和Setters
ES5 getter setter的更多相关文章
- es6 getter setter
https://stackoverflow.com/questions/34517538/setting-an-es6-class-getter-to-enumerable 1. 我要 getter ...
- 懒加载(getter\setter理解)
为什么要用懒加载 1.首先看一下程序启动过程:(如图) 会有一个mian的设置,程序一启动会加载main.storyboard main.storyboard又会加载箭头所指的控制器 控制器一旦加载, ...
- iOS getter setter
getter setter 给成员变量起名字用的 setter方法 设置成员变量值 1. setter 方法一定是对象方法 不可能是类方法 2.一定没有返回值 3. 以set开头,并且set后面跟上需 ...
- Lombok(1.14.8) - @Getter, @Setter, @ToString, @EqualsAndHashCode & @Data
@Getter / @Setter @Getter 和 @Setter,分别实现了 Gette r和 Setter 方法. package com.huey.hello.bean; import ja ...
- Java程序猿JavaScript学习笔记(4——关闭/getter/setter)
计划和完成这个例子中,音符的顺序如下: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScr ...
- lombok @Getter @Setter 使用注意事项
lombok是一个帮助简化代码的工具,通过注解的形式例如@Setter @Getter,可以替代代码中的getter和setter方法,虽然eclipse自带的setter.getter代码生成也不需 ...
- lombok(@Getter&@Setter)
Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法. 官方地址:https://project ...
- 自动生成getter setter
如何使用java黑魔法给一个entity生成getter,setter方法? 由于java是一门静态语言,要给一个类动态添加方法,看似是不可能的.但牛B的程序员会让任何事情发生.我只知道有两种方式可以 ...
- 为什么要使用getter/setter
变量私有化的好处 1. 在setter中可以加入合法性检查,比如设置颜色的函数中,对于RGB颜色要判断其值在0~255之间. 2. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...
随机推荐
- SOA架构介绍和理解
SOA架构介绍和理解 SOA的正确方法论及目标模型,其实SOA在实现架构落地上,需要考虑到对服务的组合,不断的重用现有的服务,让企业应用可以逐步集成,快速实现业务的迭代. 通过SOA架构分层将服务按照 ...
- urllib.urlretrieve的用法
urllib.urlretrieve(url, local, cbk) urllib.urlretrieve(p,'photo/%s.jpg'%p.split('/')[-4]) url要下载的网站 ...
- 玩转UICollectionViewLayout
前言: 实 现垂直方向的单列表来说,使用UITableView足以:若是需要构建横向滑动列表.gridView等直线型布局,则使用 UICollectionView+UICollectionViewF ...
- .Net 零星小知识
1. 深拷贝和浅拷贝 单纯讲这两个词,其实不容易记住区别,但是看看他们对应的英语单词就显而易见了: 深拷贝: Clone 浅拷贝: Copy 记住了这个,下面在看看详细一点的信息: Copy: 只是复 ...
- FastJSON 使用
FastJSON是一个Java语言编写的高性能,功能完善,完全支持http://json.org的标准的JSON库.多了不说了,百度一下一大把. 在此,简单的总结一下自己用过,测试过的方法. 如果使用 ...
- [转载] 纯手打 第一篇:安装配置gradle
本文转载自: http://www.cnblogs.com/uncle2000/p/4276833.html 一个bug 一个脚印的叫你们用gradle. 1介于网络上的很多资料都是老的 不适用与现在 ...
- java io流之字符流
字符流 在程序中一个字符等于两个字节,那么java提供了Reader.Writer两个专门操作字符流的类. 字符输出流:Writer Writer本身是一个字符流的输出类,此类的定义如下: publi ...
- POJ2553
题意:很难懂!但是大体意思就是求有向图中从一个节点出发到达的点也能反向到达该节点的点.如a能到{b1,b2.....bx}这些点,而这些点也能到a,则a为要求的点.题目是求出所有的这种点. 对图进行缩 ...
- FusionCharts制作报表使用XML导入数据时出现的中文乱码问题
今天在使用FusionCharts制作报表时用XML导入数据,总是出现乱码问题,下面是我的解决方案. 让FusionCharts支持中文 刚刚将XML导入到html中后,在火狐浏览器一直报Invali ...
- .NET重载运算符
代码如下: /// <summary> /// 坐标(结构类型) /// </summary> public struct Coordinate { public int x; ...