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. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...
随机推荐
- ajax回调打开新窗体防止浏览器拦截有效方法
ajax回调打开新窗体防止浏览器拦截,就这么做! 问题剖析: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function click_fun(){ window ...
- 如何在cmd下切换不同版本的Python
(1)分别安装python-2.7.12.amd64.msipython-3.5.2-amd64.exe(python官网下载的)顺序无所谓(为了看着方便,我把安装路径修改统一了)(2)配置环境变量D ...
- Sql 触发器禁用和启用
--启用or禁用指定表所有外键约束 alter table tbname NOCHECK constraint all alter table tbname CHECK constraint all ...
- [Docker] docker 基础学习笔记6(共6篇)
这个迁移指的是docker整个系统的迁移,而不是说images存储位置迁移 docker info 查看docker的各项配置 首先做文件的迁移 使用rsync软件将docker的文件夹整体迁移到 ...
- jquery 中substring,substr,split的用法
substring 方法 返回位于 String 对象中指定位置的子字符串. strVariable.substring(start, end) 参数 start 指明子字符串的起始位置,该索引从 0 ...
- ffmpeg 音频转换: use ffmpeg convert the audio from stereo to mono without changing the video part
To convert the audio from stereo to mono without changing the video part, you can use FFmpeg: ffmpeg ...
- linux 账号管理与ACL权限设定
此文涉及命令:useradd.usermod.userdel.passwd.chage.setfacl.getfacl.su.sudo.fingr.chfn.chsh.id.groupadd.grou ...
- 网页链接qq
<a href="mqqwpa://im/chat?chat_type=wpa&uin=12345678&version=1&src_type=web& ...
- JSON 的应用
使用 JSON 需要的 jar 包:
- spring boot 学习笔记(二) 构建web支持jsp
一.必须将项目打包成war包 <packaging>war</packaging> 二.pom.xml加入依赖包 <dependency> <groupId& ...