最近在学习vuejs,了解到内部实现使用到了es5的Getters和Setters。之前看高程的时候,没有重视这块,今天查看一下文档,了解了他们的作用,再次记录一下,可供以后查看和共享。

  定义Getters和Setters:(一共有三种定义方法)

 第一种方法: 使用对象字面量创建对象时,可以像下面定义set 和set一样定义,

 1 var obj = {
 2     "a": 1,
 3     get b(){
 4         return this.a + 1;
 5     },
 6     set c(val){
 7         this.a = val + this.a;
 8     }
 9 };
10
11 console.log(obj.a);   //初始值为1
12 console.log(obj.b);   //2
13 obj.c = 3;
14 console.log(obj.a);   //4

  第二种方法:通过Object.defineProperty(...)来定义

 1 var d = Date.prototype;
 2
 3 Object.defineProperty(d, "year", {
 4     get : function() {
 5         return this.getFullYear();
 6     },
 7     set: function(val) {
 8         this.setFullYear(val);
 9     }
10 });
11
12 var date = new Date();
13 console.log("*********");
14 console.log(date.year);   //2016
15 console.log("*********");

第三种方式:

 1 function Filed(val){
 2     var value = val;
 3     this.getValue = function(){
 4         return value;
 5     };
 6     this.setValue = function(val){
 7         value = value = val;
 8     };
 9 }
10
11 var f = new Filed(20);
12 console.log("\n**********************");
13 console.log(f.getValue());         //20
14 f.setValue(30);
15 console.log(f.getValue());         //30

Getters和Setters可以做什么?

  目的:给js语言增加覆盖对象单个属性默认的[[Get]]和[[Put]]能力。

  实际上,Getters和Setters都是对象上的属性,通过Getters可以调用对象上隐藏的函数来获取值,通过Setters调用隐藏的函数,来为对象属性赋值。

  我们知道对象的属性描述符有value、writable、configurable和enumerable。Getters和Setter也可被理解为对象的存取描述符。如果一个对象定义了Getter和Setter,value和writable会被忽略,js只考虑Getter、Setter、configurable和enumerable。

  

 1 var obj = {
 2     get a(){
 3         return 2;
 4     }
 5 };
 6
 7 Object.defineProperty(obj, "b", {
 8     get: function(){
 9         return this.a * 4;
10     },
11     enumerable: true
12 });
13
14 console.log(obj.a);   //2
15 console.log(obj.b);   //8
16 obj.a = 4;
17 console.log(obj.a);   //2

  在16行的时候,我们对a进行赋值,但是在17行的时候,依旧输出了2,,这是因为一旦存在存在存取描述符,并且仅设有Getter的话(即便设有Setter),对该属性的赋值会被默认忽略。

 1 var obj = {
 2     get a(){
 3         return 2;
 4     },
 5     set c(val){
 6         this.a = 3;
 7     }
 8 };
 9
10 Object.defineProperty(obj, "b", {
11     get: function(){
12         return this.a * 4;
13     },
14     enumerable: true
15 });
16
17 console.log(obj.a);   //2
18 console.log(obj.b);   //8
19 //obj.a = 4;
20 obj.c = 4;
21 console.log(obj.a);   //2

  实际使用代码如下:

 1 var myObject = {
 2     // define a getter for `a`
 3     get a() {
 4         return this._a_;
 5     },
 6
 7     // define a setter for `a`
 8     set a(val) {
 9         this._a_ = val * 2;
10     }
11 };
12
13 myObject.a = 2;
14
15 console.log(myObject.a); // 4

  通过Setter和Getter,我们可以动态设置和获取对象属性的值得效果:

 1 var expr = "foo";
 2 var obj = {
 3     a: "aa",
 4     set [expr](val){
 5         this.a = val;
 6     },
 7     get [expr](){
 8         return expr
 9     }
10 };
11
12 obj.foo="bb";
13 console.log(obj.a);   //bb
14 console.log(obj[expr]);   //foo

对于上面的动态设置和获取,不晓得实际用途。

js的[[Get]]和[[Put]]操作

Getter和Setter会对js对象属性的存取产生怎样的影响呢?

[[Get]]操作:

1 var obj = {
2     a: 2
3 };
4 console.log(obj.a);    //2

上面代码的背后的机制:

执行的时候,JavaScript 会在对象 obj上执行一次 [[Get]] 操作。JavaScript 内置的 [[Get]] 操作首先根据属性名称检查对象本身是否有该属性,如果这时候找到了,那么就返回它的值;如果没找到,那么会通过该对象的Prototype 链继续向上查找,直到顶层的 Object.prototype。见下面代码:

1 var OldObj = function(){};
2 OldObj.prototype.a = 2;
3 var obj = new OldObj();
4 console.log(obj.a);   //2

[[put]]操作:

1 var obj = {
2     a: 2
3 };
4 obj.a = 3;

背后的机制:

首先,JavaScript 会触发一个 [[Put]] 操作,它的行为会根据要赋值的属性是否已经直接存在于该对象上而有所不同。如果该属性已经存在了,[[Put]] 操作会执行如下步骤:

  1. 该属性是否已经定义了 Setter,如果已经定义了,那么调用它;
  2. 该属性的属性描述符 (Property Descriptor)是否定义了 writable: false,如果是,那么赋值操作被忽略,如果是 strict mode,那么会抛出 TypeError 异常;
  3. 如果没有上述情况,那么给已存在的属性赋值。

如果被赋值的属性不是直接存在于对象上:

  1. [[Put]] 操作首先会搜索 Prototype 链,如果没有找到 foo,那么就在被赋值的对象上直接创建 foo,并赋值为 bar
  2. 如果在 Prototype 链上找到了 foo,代码的行为就会变得诡异起来,我们回头再看。在此之前,先来了解一个概念,叫做变量隐藏 (Variable Shadowing)。当一个变量既直接存在于对象本身,又存在于对象的 Prototype 链,那我们就可以说对象本身的属性 foo 隐藏了存在于 Prototype 链的变量 foo。理解了这个概念,我们再来看当变量 foo 在 Prototype 链上存在的的时候,给 foo 赋值可能带来的三种结果:
    1. 如果 foo 在 Prototype 链上存在,并且它没有被定义为只读的 (writable: false),那么一个名叫 foo 的属性会被直接添加到 myObject,从而造成 变量隐藏 (Shadowing)
    2. 如果 foo 在 Prototype 链上存在,并且被标记为只读的 (writable: false),那么对 foo 的赋值操作会被忽略;如果是 strict mode,那么会抛出异常;
    3. 如果 foo 在 Prototype 链上存在,并且它具有 Setter,那么 Setter 始终会被调用,也就是说没有属性会被直接添加到 myObject 上,也不会发生变量隐藏。也许你还记得,当对象属性 Setter 存在的时候,给该属性赋值,不会检查 writable

原文地址:js Getters和Setters

转载于:https://www.cnblogs.com/yanyalun/p/5549883.html

ES5 getter setter相关推荐

  1. ES6-8 - 函数名/对象拓展、描述符、getter/setter

    函数名 有两种特殊情况:bind方法创造的函数,name属性返回bound加上原函数的名字:Function构造函数创造的函数,name属性返回anonymous. bind函数名 // 以bound ...

  2. TypeScript入门教程 之 类/抽象类/构造器/Getter/Setter

    TypeScript入门教程 之 类/抽象类/构造器/Getter/Setter 将JavaScript中的类作为头等项很重要的原因是: 类提供了有用的结构抽象 为开发人员提供一种一致的方式来使用类, ...

  3. lombok(@Getter@Setter)

    Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法. 官方地址:https://project ...

  4. Java程序猿JavaScript学习笔记(4——关闭/getter/setter)

    计划和完成这个例子中,音符的顺序如下: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScr ...

  5. 还在手写 Getter/Setter 方法吗?Lombok 让你的代码更简洁!

    以下是文章大纲: Lombok 是什么? 官网:https://projectlombok.org/ Lombok 是一个 Java 库,使用 Lombok 可以通过简单的注解帮助我们消除 Java ...

  6. php5.5 getter setter,实现了一个PHP5的getter/setter基类的代码

    实现了一个PHP5的getter/setter基类的代码 PHP3.PHP4都拥有类,但它们的类定义的实在很不像样,效率还挺难为情的,但资料上说PHP5重新构造了面向对象的支持,尽管并不是完全面向对象 ...

  7. SpringCloud工作笔记074---Idea2018 1.6发现不支持@Slf4j,@Getter ,@Setter注解

    技术交流QQ群[JAVA,.NET,BigData,AI]:170933152 最近发现这个问题了,好麻烦.... 1 Lombok背景介绍 官方介绍如下: Project Lombok makes ...

  8. 为什么要使用getter/setter

    变量私有化的好处 1. 在setter中可以加入合法性检查,比如设置颜色的函数中,对于RGB颜色要判断其值在0~255之间. 2. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...

  9. 利用Lambda实现通过getter/setter方法引用拿到属性名

    很多开发场景需要用到Java Bean的属性名,直接写死属性名字符串的形式容易产生bug(属性名一旦变化,IDE不会告诉你你的字符串需要同步修改).JDK8的Lambda可以通过方法引用简化代码,同样 ...

最新文章

  1. 系统异常捕捉处理设计文档
  2. AJAX中日历控件的应用
  3. Stanford机器学习笔记-1.线性回归
  4. mysql id生成器自定义_MybatisPlus使用自定义Id生成器数据自动填充
  5. (组合数学笔记)Pólya计数理论_Part.3_置换群及其性质
  6. 关于SQL Server 存储过程的EXECUTE AS CALLER选项
  7. 基本的python内置函数str(x)_Python内置函数(61)——str
  8. java浮点数转二进制_浮点数转换成二进制
  9. 论文笔记_S2D.01-2018-ICRA_Sparse-to-Dense:从稀疏深度样本+单一图像的深度预测
  10. 【新征程】1、考研路漫漫
  11. 使用奇东锐腾PXE网克工具进行批量装机和系统恢复
  12. 计算机基础内容相关的论文,有关于计算机基础论文范文
  13. Element系列之阻止el-switch冒泡事件
  14. Android:如何优雅的开发马甲包?
  15. java后台生成二维码以及页面显示二维码方式
  16. Oracle Database-数据处理和表的管理部分
  17. ftdi android,FTDI D2xx android java not reading
  18. 图片裁剪工具vueCropper跨域解决
  19. 5个简历模板下载及制作网站
  20. 工具软件 PYUV打开raw图片

热门文章

  1. 中国互联网大佬江湖拼什么?拼财力拼出身拼前景拼造势
  2. Vue组件通信原理剖析(一)事件总线的基石 $on和$emit
  3. vue init webpack vue-demo01复杂安装的详解
  4. Python Web开发:开发wsgi中间件
  5. 分布式消息队列 Kafka
  6. 关于驰骋表单引擎中字段扩展设置对文本框Pop窗体返回值的升级说明 2012/11/13...
  7. [跟我学UML] UML中的对象图
  8. C字符串数组赋值
  9. Geometric-Transformations图像几何变换halcon算子,持续更新
  10. 关于发那科机器人的FSSB