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. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...
随机推荐
- 邮箱验证 各种邮箱的smtp
常见邮箱的SMTP设置 QQ 邮箱举例:(地址test@qq.com)(账号test)(密码***)(SMTP服务smtp.qq.com)(端口25)(注意:请手动开通SMTP功能,通过网页登录qq邮 ...
- C#连接Sql Serve数据库及增,删,改操作
一:连接. string sqlconn = "server=主机名;database=数据名;integrated security=true" //integrated sec ...
- Eclipse 的常用快捷方式
快捷方式<!--[if !supportLists]-->0. Ctrl + 1 (快速修复)<!--[if !supportLists]-->1. Ctrl + D (删除当 ...
- js学习随笔
prompt 提示; parse解析;slice划分,切片;sort排序: 移除样式,removeAttribute("style") document.getElementByI ...
- python 连接redis工具类
#!/usr/bin/python # coding=utf-8 __author__ = 'shuangjiang' import redis import sys default_encoding ...
- 推送 iOS 10
1:APNs通知与应用内消息对比 极光文档上面是这么写的 后来更直接的说法是: 2:下面是介绍app不同状态下面接受到通知调用的方法: // iOS 10 Support,这个是程序在前台接受到通知是 ...
- 反汇编工具capstone安装后import error
使用sudo pip install capstone后,使用如下代码import时出现error. from capstone import * 错误信息: File "/usr/loca ...
- iOS10 的适配问题,你遇到了吗?导航栏标题和返回按钮神奇的消失了
苹果系统升级后好多应用都发了新版本来适配,今天就来分享一下我的适配历程. 首先是出现的问题: 1.push一个控制器,返回按钮和标题神奇的消失了,打开三维视图(比较坑的是有的版本老到打不开三维视图 ) ...
- HTML实体符号代码速查表
1.特色的 © © © 版权标志 | | 竖线,常用作菜单或导航中的分隔符 · · · 圆点,有时被用来作为菜单分隔符 ↑ ↑ ↑ 上箭头,常用作网页“返回页面顶部”标识 € € € 欧元标识 ² ...
- JVM内存模型和性能优化
JVM内存模型优点 内置基于内存的并发模型: 多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...