博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES5 getter setter
阅读量:4307 次
发布时间:2019-06-06

本文共 4234 字,大约阅读时间需要 14 分钟。

    最近在学习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);   //初始值为112 console.log(obj.b);   //213 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);   //201615 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());         //2014 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: true12 });13 14 console.log(obj.a);   //215 console.log(obj.b);   //816 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: true15 });16 17 console.log(obj.a);   //218 console.log(obj.b);   //819 //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);   //bb14 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

原文地址:

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

你可能感兴趣的文章
Git基础(三)--常见错误及解决方案
查看>>
Git(四) - 分支管理
查看>>
PHP Curl发送数据
查看>>
HTTP协议
查看>>
HTTPS
查看>>
git add . git add -u git add -A区别
查看>>
apache下虚拟域名配置
查看>>
session和cookie区别与联系
查看>>
PHP 实现笛卡尔积
查看>>
Laravel中的$loop
查看>>
CentOS7 重置root密码
查看>>
Centos安装Python3
查看>>
PHP批量插入
查看>>
laravel连接sql server 2008
查看>>
Laravel 操作redis的各种数据类型
查看>>
Laravel框架学习笔记之任务调度(定时任务)
查看>>
laravel 定时任务秒级执行
查看>>
浅析 Laravel 官方文档推荐的 Nginx 配置
查看>>
Swagger在Laravel项目中的使用
查看>>
Laravel 的生命周期
查看>>