JS中setter/getter理解

  • JS对象属性
    • get/set和getter/setter
  • 数据属性
  • Object.defineProperty()
  • 访问器属性
  • getter/setter创建及删除
    • getter
    • getter创建:
    • getter删除:
    • setter
    • setter创建:
    • setter删除:
  • 应用
    • Vue响应式原理
  • 参考文章

JS对象属性

JS中对象包括属性和方法,其中属性又可分为数据属性和访问器属性。数据属性一般用于存储数据数值;访问器属性不包含数据值,访问器属性多用于get/set操作。本文讨论的setter/getter就是JS对象访问器属性中的get/set操作。

get/set和getter/setter

当属性拥有get/set特性时,属性就是访问器属性。代表着在访问属性或者写入属性值时,对返回值做附加的操作。而这个操作就是getter/setter函数。

它们只能应用到单个属性上,无法应用在整个对象上。getter/setter是隐藏函数,是访问器属性默认拥有的隐藏函数。在读取访问器属性时调用getter,返回有效的值;在写入访问器属性时调用setter函数并传入新值。

不管是对象文字语法中的get a(){…},还是的defineProperty(…)中的显式定义,二者都会在对象中创造一个不包含值的属性,对于这个属性的访问会自动调用一个隐藏函数,它的返回值会被当做属性访问的返回值。

数据属性

数据属性是用于存储数据数值的,因此数据属性具有一个数据值的位置,在这个位置可以读取和写入值。数据属性有4个描述其行为的特性:

  1. 【Configurable】默认值为true。表示:a、能否通过delete删除属性从而重新定义属性, b、能修改属性的特性 ,c、能够把属性由数据属性修改为访问器属性;
  2. 【Enumerable】默认值为true,表示能否通过for-in循环返回该属性;
  3. 【Writable】默认值为true,表示能否修改属性的值(这是与【Configurable】不同之处)
  4. 【Value】默认值为undefined,这个值即为属性的属性值,我们可以在这个位置上读取属性值,也可以在这个位置上写入属性值。

Object.defineProperty()

Object.defineProperty()方法k修改属性默认的特性,此方法接收三个参数:属性所在的对象、属性的名字和一个描述符对象。描述符对象是对象字面量的方法创建的,里面的属性和属性值是要修改的特性和特性值。
需要注意的是:

  1. 数据属性有4个特性中,除Value外其余三个默认为ture,这是在创建对象并创建属性的情况下的默认值。对于直接通过调用Object.defineProperty()方法创建的属性,这三个特性的默认值均为false。
  2. 一旦属性被设置成为不可配置的,就不能再把它变回可配置了。因此为了可配置,必须在第一次调用Object.defineProperty()函数时就将默认值修改为true。

访问器属性

访问器属性不包含数据值,他们包含一对getter函数和setter函数。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性是,会调用setter函数并传入新值,这个函数负责决定如何处理数据。访问器属性不能直接定义,必须是用Object.defineProperty()来定义。
访问器属性有4个描述其行为的特性:

  1. 【Configurable】默认值为true
  2. 【Enumerable】默认值为true,表示能否通过for-in循环返回该属性
  3. 【Get】在读取属性时调用的函数。默认值为undefined。
  4. 【Set】在写入属性时调用的函数。默认值为undefined。
    由于get和set函数也属于属性的特性,那么他们就有可能出现在Object.defineproperty的第三个参数描述符对象的属性中。

getter/setter创建及删除

getter

  1. 可以使用数值或字符串作为标识;
  2. 必须不带参数;
  3. 它不能与另一个 get或具有相同属性的数据同时出现在一个对象字面量中
  4. 可通过 delete 操作符删除 getter

getter创建:

  1. 对象初始化时定义
const obj = {log: ['a', 'b', 'c'],get latest() {if (this.log.length === 0) {return undefined;}return this.log[this.log.length - 1];}
};
console.log(obj.latest);
// expected output: "c"
  1. 使用defineProperty在现有对象上定义
const obj = {log: ['a', 'b', 'c'],
};
Object.defineProperty(obj, 'latest', {get:function() {return this.log;},
});
console.log(obj.latest);
// expected output: ["a", "b", "c"]

注意:当使用 get 关键字时,它和Object.defineProperty() 有类似的效果,在classes中使用时,二者有细微的差别。当使用 get 关键字时,属性将被定义在实例的原型上,当使用Object.defineProperty()时,属性将被定义在实例自身上。

  1. 使用计算出的属性名
let expr = 'foo';
let obj = {get [expr]() { return 'bar'; }
};
console.log(obj.foo); // "bar"

getter删除:

使用delete操作符删除 getter

delete obj.latest;

setter

  1. 它的标识符可以是数字或字符串;
  2. 必须有一个明确的参数;
  3. 在对象字面量中,不能为一个已有真实值的变量使用 set ,也不能为一个属性设置多个 set
  4. 可通过 delete 操作符删除 setter

setter创建:

  1. 对象初始化时定义
const language = {set current(name) {this.log.push(name);},log: []
};
language.current = 'EN';
language.current = 'FA';
console.log(language.log);
// expected output: Array ["EN", "FA"]
  1. 使用defineProperty在现有对象上定义
const o = { a:0 };
Object.defineProperty(o, "b", { set: function (x) { this.a = x / 2; } });
o.b = 10; // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
console.log(o.a) // 5
  1. 使用计算属性名
const expr = "foo";
const obj = {baz: "bar",set [expr](v) { this.baz = v; }
};
console.log(obj.baz); // "bar"
obj.foo = "baz";      // run the setter
console.log(obj.baz); // "baz"

setter删除:

使用delete操作符删除 setter

delete language.current;

应用

JS中setter/getter的实际应用场景之一就是Vue响应式原理。

Vue响应式原理

Vue响应式原理:数据发生变化后重新渲染页面
为实现Vue响应式原理,需要完成的的是:

  1. 数据劫持 / 数据代理:侦测数据的变化
  2. 依赖收集:收集视图依赖了哪些数据
  3. 发布订阅模式:数据变化时,自动“通知”需要更新的视图部分,并进行更新

其中,侦测数据变化便是采用setter/getter完成。在将对象传入Vue实例中的data选项中时,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

注意:Vue 通过Object.defineProperty来将对象的key转换成getter/setter的形式来追踪变化,但getter/setter只能追踪一个数据是否被修改,无法追踪新增属性和删除属性。故而,Vue 不能检测数组和对象的变化。

参考文章

  1. 深入理解JavaScript中的属性和特性
  2. getter
  3. setter
  4. vue响应式详解
  5. 深入响应式原理

JS中setter/getter理解相关推荐

  1. Javascript基础进阶(十六)JS中面向对象的理解、继承、封装、多态

    小编推荐:Fundebug提供JS错误监控.微信小程序错误监控.微信小游戏错误监控,Node.j错误监控和Java错误监控.真的是一个很好用的错误监控费服务,众多大佬公司都在使用. 面向对象编程OOP ...

  2. 谈谈我对js中闭包的理解

    闭包是一个能够访问其他函数作用域的函数. 很显然这样的定义晦涩难懂,很多人都很难理解闭包的真正含义 那么我们就用通俗一点的语言来解析一下什么是闭包 我在知乎上看到一个比较有意思的回答: 由此我们可以通 ...

  3. js中this的理解

    平常用this很多,对this的理解就是this是对应执行环境,然而很多时候效果并不是想要的,最近看了一些谈到this的笔记和书籍,总结下. 对this的误解: this是指向函数本身 先上个demo ...

  4. JS中call用法理解

    call()方法是借用构造函数来实现继承,即在子类型构造函数的内部调用超类型构造函数. 我理解的call()的作用就是改变上下文,即在以下代码中的 function subtype(){superTy ...

  5. js中深浅拷贝理解与方法

    深浅拷贝的方法 堆栈理解 基本数据类型 number.string.boolean.null.undefined 引用数据类型 object.function.array 栈内存 存储基本数据类型内容 ...

  6. js中call函数理解

    一直以来,对call函数都不是很理解,经常看到用,有时候把,觉得挺好理解的,有时候吧,又觉得摸不清头脑,最近在看d3,里面又遇到call,所以,还是得把这个问题理解透彻.现在把我的理解记录如下: ca ...

  7. JS中prototype的理解

    1,JS是基于对象的语言,构造函数本身就是一个对象,当调用new关键字时,会创建一个新对象.2,prototype是对象的一个属性,其可以是一个基本类型,如数字.字符串等,也可以是一个引用类型. 3, ...

  8. js中arguments的理解

    一.在函数调用的时候,浏览器每次都会传递进来两个隐式参数 1.函数的上下文对象this 2.封装实参的对象arguments 二.arguments对象 1.arguments对象实际是所在函数的一个 ...

  9. JS 中 TDZ 的理解

    原文链接:https://acrens.github.io/2017/01/22/2017-01-22-TDZ/ 春节快到了,假期也快到了,空闲之余刷个微博,看见 @ruanyf 提出了一个问题与 T ...

最新文章

  1. php session_start() 非常慢,PHP session_start()很慢问题分析与解决办法
  2. linux ssh 设置的相关总结(ssh最大连接数、ssh连接时长、安全性配置等)
  3. git提交输入密码_git提交到自己的服务器,每次都要输入密码
  4. CobaltStrike的使用
  5. 阿里巴巴大数据实践—实时技术
  6. [蓝桥杯][2019年第十届真题c/c++B组]后缀表达式(解释sum -= 2*a[i])
  7. (HDU)1061 --Rightmost Digit( 最右边的数字)
  8. Oracle数据库备份到本地
  9. 卡诺模型案例分析_需求分析神器 | 卡诺模型
  10. 如何解决Adobe Flash Player已被屏蔽
  11. js base64 php,php中的base64decode 与js中的互相转换
  12. android studio运行时报错AVD Nexus_5X_API_P is already running解决办法
  13. win7 关闭防火墙
  14. 信必优荣获BOSS直聘“王者之舟·最爱人才雇主奖”
  15. 喵喵机和咕咕机哪个好,打印效果大评测!喵喵机p2 VS咕咕机GT1
  16. 逆序数(inverse number)
  17. linux下eeprom测试函数,Linux Kernel eisa_eeprom_read函数绕过安全检查漏洞
  18. 使用devops的团队_DevOps团队如何为网络星期一做准备
  19. Python:使用f-string保留小数点位数
  20. 高阶自动驾驶量产背后,最严监管或将加速落地

热门文章

  1. SMR叠瓦盘原理及终极使用指南
  2. GoLang之M如何找工作(13)
  3. 微分方程计算机仿真国内外研究论文,功率键合图法在血液循环系统计算机仿真中的应用,毕业论文...
  4. Win10配置IIS与 C#/.net项目的发布与IIS部署
  5. 第31届南京地区研究生通信年会录用论文集
  6. 阿里云ECS同区域不同账户内网互相访问配置
  7. Matlab 内置函数作图、实现斐波那契数列的多种函数形式(wzl)
  8. 人总是欲望着他者的欲望
  9. 将车辆数据集kitti转换为VOC格式(车辆检测)
  10. 2019-10-31-ASP.NET-Core-连接-GitLab-与-MatterMost-打造-devops-工具