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. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...
随机推荐
- JDBC步骤
总结JDBC五步骤: 1.Class.forName 加载驱动 2.conn = (Connection) DriverManager.getConnection(url, user, passwor ...
- Math
Math.sin(t) // sin(t) Math.power(x,2*i) // x的2i次方 (double)(Math.round(sum*1000000))/1000000; / ...
- css中外边距合并
最近在布局时遇到一个有趣的问题 <style> #div1{width:200px;height:200px;background:red;} #div2{width:50px;heig ...
- MVC 之 T4模板简介
个人网站地址:nee32.com 一.T4模板内容简介 为了更好地学习T4模板,我们安装一个插件tangible T4 Editor 在使用了EF生成实体类后,我们会发现一个.tt后缀的文件,它就是T ...
- 如何把apdu[decode_len]打印出来
memcpy(data, &apdu[decode_len], apdu_len - decode_len); int i = 0; for(i=0;i<apdu_len;i ...
- jQuery事件对象event的属性和方法
事件处理(事件对象.目标元素的获取,事件对象的属性.方法等)在不同浏览器之间存在差异,jQuery在遵循W3C规范的情况下做了封装统一 一.事件对象常用的属性: event.type:获取事件的类型, ...
- java : 包装类 缓冲机制的使用(转载)
摘要: 八种基本数据类型和其包装类中 Integer valueOf(int i).Byte valueOf(byte b).Short valueOf(short s).Long valueOf(l ...
- allegro - 层叠相关参数
层叠结构设置 弹出Layout Cross Section对话框 Subclass Name一列是该层的名称,可以按照自己的需要来填写.Type 列选择该层的类型,有三种: ·CONDUCTOR: ...
- Android sharePreference使用
SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数. SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/ ...
- [转]CryptographyHelper.cs
using System; using System.IO; using System.Security.Cryptography; using System.Text; public class C ...