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邮 ...
- 史航416第11次作业&总结
作业1:冒泡排序 #include <stdio.h> ],int n); int main() { ],n,i; printf("输入一个整数n:"); scanf( ...
- Cdnbes负载均衡的权重用法解释
(1)相同域名添加两条记录,解析不同的ip,可以设置权重,比如权重2,就意思占百分之20 ,数字越大,优先级越大 (2)这个hash 如果用户访问的源是挂掉的.会去第二个源
- Sharif University CTF 2016 -- Android App
很多种的方案: 方案 A: 直接逆向读代码方案 B: 解包,加入debug信息,重新打包,动态调试方案 C: 解包,改代码加入log.i整出flag, 去掉MainActivity里面d=什么也可以, ...
- SQL语言
SQL语言的分类:DDL DML DQL DCL SQL中的操作无非就是(增删改查) DDL:Data Query Language,数据查询语言! 主要是用来定义和维护数据库的各种操作对象,比如库. ...
- 初学c# -- 学习笔记(六) winfrom组件圆角
刚好用到这个功能,看了好些例子.我就不明白,简单的一个事,一些文章里的代码写的那个长啊,还让人看么. 精简后,就其实一点,只要有paint事件的组件,都可画圆角,没有的外面套一个panel就行了. u ...
- NLua - 基于Lua的C#脚本引擎
Nlua NLua is the bind between Lua world and the .NET world. NLua is a fork of project LuaInterface ( ...
- java.sql.SQLException: ORA-00911: invalid character 解决方法
java.sql.SQLException: ORA-00911: invalid character 控制台抛出这个异常:java.sql.SQLException: ORA-00911: inva ...
- LeetCode OJ 114. Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place. For example,Given 1 / \ 2 5 / \ \ 3 4 6 T ...
- Android 获取当前时间问题1
获取的写法如下: Calendar c = Calendar.getInstance();//可以对每个时间域单独修改 int year = c.get(Calendar.YEAR); int mon ...